DUNE-FEM (unstable)

dgelliptic.hh
1/**************************************************************************
2
3 The dune-fem module is a module of DUNE (see www.dune-project.org).
4 It is based on the dune-grid interface library
5 extending the grid interface by a number of discretization algorithms
6 for solving non-linear systems of partial differential equations.
7
8 Copyright (C) 2003 - 2015 Robert Kloefkorn
9 Copyright (C) 2003 - 2010 Mario Ohlberger
10 Copyright (C) 2004 - 2015 Andreas Dedner
11 Copyright (C) 2005 Adrian Burri
12 Copyright (C) 2005 - 2015 Mirko Kraenkel
13 Copyright (C) 2006 - 2015 Christoph Gersbacher
14 Copyright (C) 2006 - 2015 Martin Nolte
15 Copyright (C) 2011 - 2015 Tobias Malkmus
16 Copyright (C) 2012 - 2015 Stefan Girke
17 Copyright (C) 2013 - 2015 Claus-Justus Heine
18 Copyright (C) 2013 - 2014 Janick Gerstenberger
19 Copyright (C) 2013 Sven Kaulman
20 Copyright (C) 2013 Tom Ranner
21 Copyright (C) 2015 Marco Agnese
22 Copyright (C) 2015 Martin Alkaemper
23
24
25 The dune-fem module is free software; you can redistribute it and/or
26 modify it under the terms of the GNU General Public License as
27 published by the Free Software Foundation; either version 2 of
28 the License, or (at your option) any later version.
29
30 The dune-fem module is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License along
36 with this program; if not, write to the Free Software Foundation, Inc.,
37 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38
39**************************************************************************/
40#ifndef DGELLIPTIC_HH
41#define DGELLIPTIC_HH
42
44
45#include <dune/fem/operator/common/differentiableoperator.hh>
46#include <dune/fem/operator/common/operator.hh>
47#include <dune/fem/operator/common/stencil.hh>
48#include <dune/fem/quadrature/cachingquadrature.hh>
49#include <dune/fem/operator/common/temporarylocalmatrix.hh>
50
51#include <dune/fem/schemes/elliptic.hh>
52
53// EllipticOperator
54// ----------------
55
56template <class DFSpace>
57struct DefaultPenalty
58{
59 DefaultPenalty(const DFSpace &space, double penalty)
60 : space_(space)
61 , penalty_(penalty)
62 {}
63 template <class Intersection>
64 double operator()(const Intersection &intersection,
65 double intersectionArea, double area, double nbArea) const
66 {
67 const double hInv = intersectionArea / std::min( area, nbArea );
68 return penalty_ * hInv;
69 }
70 const double &factor() const { return penalty_; }
71 private:
72 const DFSpace &space_;
73 double penalty_;
74};
75
76template< class DiscreteFunction, class Model,
77 class Penalty = DefaultPenalty<typename DiscreteFunction::DiscreteFunctionSpaceType > >
78struct DGEllipticOperator
79: public virtual Dune::Fem::Operator< DiscreteFunction >
80{
81 typedef DiscreteFunction DiscreteFunctionType;
82 typedef Model ModelType;
83
84 typedef DiscreteFunction DomainDiscreteFunctionType;
85 typedef DiscreteFunction RangeDiscreteFunctionType;
86protected:
87 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
88 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
89 typedef typename LocalFunctionType::RangeType RangeType;
90 typedef typename LocalFunctionType::JacobianRangeType JacobianRangeType;
91
92 typedef typename DiscreteFunctionSpaceType::IteratorType IteratorType;
93 typedef typename IteratorType::Entity EntityType;
94 typedef typename EntityType::Geometry GeometryType;
95
96 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
97
98 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
99 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
100 typedef typename IntersectionIteratorType::Intersection IntersectionType;
101 typedef typename IntersectionType::Geometry IntersectionGeometryType;
102
103 typedef Dune::Fem::ElementQuadrature< GridPartType, 1 > FaceQuadratureType;
105
106 static const int dimDomain = LocalFunctionType::dimDomain;
107 static const int dimRange = LocalFunctionType::dimRange;
108
109public:
111 DGEllipticOperator ( const DiscreteFunctionSpaceType &space,
112 const ModelType &model,
113 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
114 : model_( model ),
115 penalty_( space, parameter.getValue< double >( "penalty", 40 ) ),
116 grdSzeInt_( 0 )
117 {
118 // std::cout << "dg operator with penalty:" << penalty_.factor() << std::endl;
119 }
120
121 DGEllipticOperator ( const DiscreteFunctionSpaceType &dSpace,
122 const DiscreteFunctionSpaceType &rSpace,
123 const ModelType &model,
124 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
125 : model_( model ),
126 penalty_( dSpace, parameter.getValue< double >( "penalty", 40 ) ),
127 grdSzeInt_( 0 )
128 {
129 // std::cout << "dg operator with penalty:" << penalty_.factor() << std::endl;
130 }
131
133 virtual void operator() ( const DomainDiscreteFunctionType &u, RangeDiscreteFunctionType &w ) const
134 { apply(u,w); }
135 template <class GF>
136 void apply( const GF &u, RangeDiscreteFunctionType &w ) const;
137
138 size_t gridSizeInterior() const { return grdSzeInt_; }
139
140protected:
141 const ModelType &model () const { return model_; }
142 Penalty penalty() const { return penalty_; }
143
144protected:
145 const ModelType &model_;
146 Penalty penalty_;
147 mutable size_t grdSzeInt_;
148};
149
150// DifferentiableDGEllipticOperator
151// ------------------------------
152
153template< class JacobianOperator, class Model,
154 class Penalty = DefaultPenalty<typename JacobianOperator::DomainFunctionType::DiscreteFunctionSpaceType > >
155struct DifferentiableDGEllipticOperator
156: public DGEllipticOperator< typename JacobianOperator::DomainFunctionType, Model, Penalty >,
157 public Dune::Fem::DifferentiableOperator< JacobianOperator >
158{
159 typedef DGEllipticOperator< typename JacobianOperator::DomainFunctionType, Model, Penalty > BaseType;
160
161 typedef JacobianOperator JacobianOperatorType;
162
163 typedef typename BaseType::DiscreteFunctionType DiscreteFunctionType;
164 typedef typename BaseType::ModelType ModelType;
165 typedef typename BaseType::DomainDiscreteFunctionType DomainDiscreteFunctionType;
166 typedef typename BaseType::RangeDiscreteFunctionType RangeDiscreteFunctionType;
167
168protected:
169 typedef typename DomainDiscreteFunctionType::DiscreteFunctionSpaceType DomainDiscreteFunctionSpaceType;
170 typedef typename DomainDiscreteFunctionType::LocalFunctionType DomainLocalFunctionType;
171 typedef typename DomainLocalFunctionType::RangeType DomainRangeType;
172 typedef typename DomainLocalFunctionType::JacobianRangeType DomainJacobianRangeType;
173 typedef typename RangeDiscreteFunctionType::DiscreteFunctionSpaceType RangeDiscreteFunctionSpaceType;
174 typedef typename RangeDiscreteFunctionType::LocalFunctionType RangeLocalFunctionType;
175 typedef typename RangeLocalFunctionType::RangeType RangeRangeType;
176 typedef typename RangeLocalFunctionType::JacobianRangeType RangeJacobianRangeType;
177
178 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
179 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
180 typedef typename LocalFunctionType::RangeType RangeType;
182 typedef typename LocalFunctionType::JacobianRangeType JacobianRangeType;
183
184 typedef typename DiscreteFunctionSpaceType::IteratorType IteratorType;
185 typedef typename IteratorType::Entity EntityType;
186 typedef typename EntityType::Geometry GeometryType;
187
188 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
189
190 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
191 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
192 typedef typename IntersectionIteratorType::Intersection IntersectionType;
193 typedef typename IntersectionType::Geometry IntersectionGeometryType;
194
195 typedef Dune::Fem::ElementQuadrature< GridPartType, 1 > FaceQuadratureType;
197
198 static const int dimDomain = LocalFunctionType::dimDomain;
199 static const int dimRange = LocalFunctionType::dimRange;
200
201public:
203 DifferentiableDGEllipticOperator ( const DiscreteFunctionSpaceType &space,
204 const ModelType &model,
205 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
206 : BaseType( space, model, parameter )
207 {}
208 DifferentiableDGEllipticOperator ( const DiscreteFunctionSpaceType &dSpace,
209 const DiscreteFunctionSpaceType &rSpace,
210 const ModelType &model,
211 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
212 : BaseType( dSpace, rSpace, model, parameter )
213 {}
214
216 void jacobian ( const DomainDiscreteFunctionType &u, JacobianOperatorType &jOp ) const
217 { apply(u,jOp); }
218 template <class GridFunctionType>
219 void apply ( const GridFunctionType &u, JacobianOperatorType &jOp ) const;
220 using BaseType::apply;
221
222protected:
223 using BaseType::model;
224 using BaseType::penalty;
225 using BaseType::grdSzeInt_;
226};
227
228// Implementation of DGEllipticOperator
229// ----------------------------------
230
231template< class RangeDiscreteFunction, class Model, class Penalty >
232template<class GF>
233void DGEllipticOperator< RangeDiscreteFunction, Model, Penalty >
234 ::apply( const GF &u, RangeDiscreteFunctionType &w ) const
235{
236 // clear destination
237 w.clear();
238
239 // get discrete function space
240 const DiscreteFunctionSpaceType &dfSpace = w.space();
241 Dune::Fem::ConstLocalFunction< GF > uLocal( u );
242 Dune::Fem::ConstLocalFunction< GF > uOutLocal( u );
243 Dune::Fem::AddLocalContribution< RangeDiscreteFunctionType > wLocal( w );
244
245 grdSzeInt_ = 0;
246
247 // iterate over grid
248 const IteratorType end = dfSpace.end();
249 for( IteratorType it = dfSpace.begin(); it != end; ++it )
250 {
251 // get entity (here element)
252 const EntityType &entity = *it;
253
254 // increase element counter
255 ++grdSzeInt_;
256
257 bool needsCalculation = model().init( entity );
258 if (! needsCalculation )
259 continue;
260
261 // get elements geometry
262 const GeometryType &geometry = entity.geometry();
263
264 // get local representation of the discrete functions
265 auto uGuard = Dune::Fem::bindGuard( uLocal, entity );
266 auto wGuard = Dune::Fem::bindGuard( wLocal, entity );
267
268 // obtain quadrature order
269 const int quadOrder = uLocal.order() + wLocal.order();
270
271 { // element integral
272 QuadratureType quadrature( entity, quadOrder );
273 const size_t numQuadraturePoints = quadrature.nop();
274 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
275 {
276 const typename QuadratureType::CoordinateType &x = quadrature.point( pt );
277 const double weight = quadrature.weight( pt ) * geometry.integrationElement( x );
278
279 RangeType vu;
280 uLocal.evaluate( quadrature[ pt ], vu );
281 JacobianRangeType du;
282 uLocal.jacobian( quadrature[ pt ], du );
283
284 // compute mass contribution (studying linear case so linearizing around zero)
285 RangeType avu( 0 );
286 model().source( quadrature[ pt ], vu, du, avu );
287 avu *= weight;
288 // add to local functional wLocal.axpy( quadrature[ pt ], avu );
289
290 JacobianRangeType adu( 0 );
291 // apply diffusive flux
292 model().flux( quadrature[ pt ], vu, du, adu );
293 adu *= weight;
294
295 // add to local function
296 wLocal.axpy( quadrature[ pt ], avu, adu );
297 }
298 }
299 if ( ! dfSpace.continuous() )
300 {
301 const double area = entity.geometry().volume();
302 const IntersectionIteratorType iitend = dfSpace.gridPart().iend( entity );
303 for( IntersectionIteratorType iit = dfSpace.gridPart().ibegin( entity ); iit != iitend; ++iit ) // looping over intersections
304 {
306 const IntersectionType &intersection = *iit;
307 if ( intersection.neighbor() )
308 {
309 const EntityType outside = intersection.outside() ;
310
311 typedef typename IntersectionType::Geometry IntersectionGeometryType;
312 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
313
314 // compute penalty factor
315 const double intersectionArea = intersectionGeometry.volume();
316 const double beta = penalty()(intersection,intersectionArea,area,outside.geometry().volume());
317
318 auto uOutGuard = Dune::Fem::bindGuard( uOutLocal, outside );
319
320 FaceQuadratureType quadInside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::INSIDE );
321 FaceQuadratureType quadOutside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::OUTSIDE );
322 const size_t numQuadraturePoints = quadInside.nop();
324
325 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
326 {
328 // get coordinate of quadrature point on the reference element of the intersection
329 const typename FaceQuadratureType::LocalCoordinateType &x = quadInside.localPoint( pt );
330 DomainType normal = intersection.integrationOuterNormal( x );
331 double faceVol = normal.two_norm();
332 normal /= faceVol; // make it into a unit normal
333 const double weight = quadInside.weight( pt ) * faceVol;
334
335 RangeType vuIn,vuOut;
336 JacobianRangeType duIn, duOut;
337 uLocal.evaluate( quadInside[ pt ], vuIn );
338 uLocal.jacobian( quadInside[ pt ], duIn );
339 uOutLocal.evaluate( quadOutside[ pt ], vuOut );
340 uOutLocal.jacobian( quadOutside[ pt ], duOut );
341 RangeType jump = vuIn - vuOut;
342 // compute -0.5 * [u] x normal
343 JacobianRangeType dvalue;
344 for (int r=0;r<dimRange;++r)
345 for (int d=0;d<dimDomain;++d)
346 dvalue[r][d] = -0.5 * normal[d] * jump[r];
347 JacobianRangeType aduIn,aduOut;
348 model().init( outside );
349 model().flux( quadOutside[ pt ], vuOut, duOut, aduOut );
350 auto pFactor = model().penalty( quadOutside[ pt ], vuOut );
351 model().init( entity );
352 model().flux( quadInside[ pt ], vuIn, duIn, aduIn );
353 JacobianRangeType affine;
354 model().flux( quadInside[ pt ], RangeType(0), JacobianRangeType(0), affine);
355 pFactor += model().penalty( quadInside[ pt ], vuIn );
357
359 RangeType value;
360 JacobianRangeType advalue;
361 // penalty term : beta [u] [phi] = beta (u+ - u-)(phi+ - phi-)=beta (u+ - u-)phi+
362 value = jump;
363 for (unsigned int r=0;r<dimRange;++r)
364 value[r] *= beta * pFactor[r]/2.;
365 // {A grad u}.[phi] = {A grad u}.phi+ n_+ = 0.5*(grad u+ + grad u-).n_+ phi+
366 aduIn += aduOut;
367 aduIn *= -0.5;
368 aduIn.umv(normal,value);
369 // [ u ] * { {A} grad phi_en } = -normal(u+ - u-) * 0.5 {A} grad phi_en
370 // we actually need G(u)tau with G(x,u) = d/sigma_j D_i(x,u,sigma)
371 // - we might need to assume D(x,u,sigma) = G(x,u)sigma + affine(x)
372 model().flux( quadInside[ pt ], vuIn, dvalue, advalue );
373 // advalue -= affine;
374
375 value *= weight;
376 advalue *= weight;
377 wLocal.axpy( quadInside[ pt ], value, advalue );
379 }
380 }
381 else if( intersection.boundary() )
382 {
383 std::array<int,dimRange> components;
384 components.fill(0);
385 model().isDirichletIntersection( intersection, components);
386
387 typedef typename IntersectionType::Geometry IntersectionGeometryType;
388 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
389
390 // compute penalty factor
391 const double intersectionArea = intersectionGeometry.volume();
392 const double beta = penalty()(intersection,intersectionArea,area,area);
393
394 FaceQuadratureType quadInside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::INSIDE );
395 const size_t numQuadraturePoints = quadInside.nop();
396
397 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
398 {
399 const typename FaceQuadratureType::LocalCoordinateType &x = quadInside.localPoint( pt );
400 const DomainType normal = intersection.integrationOuterNormal( x );
401 const double weight = quadInside.weight( pt );
402
403 RangeType bndValue;
404 model().dirichlet(1, quadInside[pt], bndValue);
405
406 RangeType value;
407 JacobianRangeType dvalue,advalue;
408
409 RangeType vuIn,jump;
410 JacobianRangeType duIn, aduIn;
411 uLocal.evaluate( quadInside[ pt ], vuIn );
412 uLocal.jacobian( quadInside[ pt ], duIn );
413 jump = vuIn;
414 jump -= bndValue;
415
416 // penalty term : beta [u] [phi] = beta (u+ - u-)(phi+ - phi-)=beta (u+ - u-)phi+
417 auto pFactor = model().penalty( quadInside[ pt ], vuIn );
418 value = jump;
419 for (unsigned int r=0;r<dimRange;++r)
420 value[r] *= beta * pFactor[r] * intersectionGeometry.integrationElement( x );
421
422 // [ u ] * { grad phi_en } = -normal(u+ - u-) * 0.5 grad phi_en
423 // here we need a diadic product of u x n
424 for (int r=0;r<dimRange;++r)
425 for (int d=0;d<dimDomain;++d)
426 dvalue[r][d] = -0.5 * normal[d] * jump[r];
427
428 model().flux( quadInside[ pt ], jump, dvalue, advalue );
429
430 // consistency term
431 // {A grad u}.[phi] = {A grad u}.phi+ n_+ = 0.5*(grad u+ + grad u-).n_+ phi+
432 model().flux( quadInside[ pt ], vuIn, duIn, aduIn );
433 aduIn.mmv(normal,value);
434
435 for (int r=0;r<dimRange;++r)
436 if (!components[r]) // do not use dirichlet constraints here
437 {
438 value[r] = 0;
439 advalue[r] = 0;
440 }
441
442 value *= weight;
443 advalue *= weight;
444 wLocal.axpy( quadInside[ pt ], value, advalue );
445 }
446 }
447 }
448 }
449
450 }
451
452 // communicate data (in parallel runs)
453 w.communicate();
454}
455
456// Implementation of DifferentiableDGEllipticOperator
457// ------------------------------------------------
458template< class JacobianOperator, class Model, class Penalty >
459template<class GF>
460void DifferentiableDGEllipticOperator< JacobianOperator, Model, Penalty >
461 ::apply ( const GF &u, JacobianOperator &jOp ) const
462{
463 // std::cout << "starting assembly\n";
464 // Dune::Timer timer;
465 typedef typename DiscreteFunctionSpaceType::BasisFunctionSetType BasisFunctionSetType;
467
468 const DomainDiscreteFunctionSpaceType &domainSpace = jOp.domainSpace();
469 const RangeDiscreteFunctionSpaceType &rangeSpace = jOp.rangeSpace();
470
472 jOp.reserve(stencil);
473 jOp.clear();
474
475 Dune::Fem::ConstLocalFunction< GF > uLocal( u );
476 TmpLocalMatrixType jLocal( domainSpace, rangeSpace );
477 TmpLocalMatrixType localOpNb( domainSpace, rangeSpace );
478
479 const GridPartType& gridPart = rangeSpace.gridPart();
480
481 const unsigned int numDofs = rangeSpace.blockMapper().maxNumDofs() *
482 DiscreteFunctionSpaceType :: localBlockSize ;
483
484 std::vector< RangeType > phi( numDofs );
485 std::vector< JacobianRangeType > dphi( numDofs );
486
487 std::vector< RangeType > phiNb( numDofs );
488 std::vector< JacobianRangeType > dphiNb( numDofs );
489
490 grdSzeInt_ = 0;
491
492 // std::cout << " in assembly: start element loop size=" << rangeSpace.gridPart().grid().size(0) << " time= " << timer.elapsed() << std::endl;;
493 const IteratorType end = rangeSpace.end();
494 for( IteratorType it = rangeSpace.begin(); it != end; ++it )
495 {
496 const EntityType &entity = *it;
497
498 // count interior elements
499 ++grdSzeInt_;
500
501 bool needsCalculation = model().init( entity );
502 if (! needsCalculation )
503 continue;
504
505 const GeometryType geometry = entity.geometry();
506
507 auto uGuard = Dune::Fem::bindGuard( uLocal, entity );
508
509 jLocal.bind( entity, entity );
510 jLocal.clear();
511
512 const BasisFunctionSetType &baseSet = jLocal.domainBasisFunctionSet();
513 const unsigned int numBaseFunctions = baseSet.size();
514
515 QuadratureType quadrature( entity, 2*rangeSpace.order() );
516 const size_t numQuadraturePoints = quadrature.nop();
517 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
518 {
519 const typename QuadratureType::CoordinateType &x = quadrature.point( pt );
520 const double weight = quadrature.weight( pt ) * geometry.integrationElement( x );
521
522 // evaluate all basis functions at given quadrature point
523 baseSet.evaluateAll( quadrature[ pt ], phi );
524
525 // evaluate jacobians of all basis functions at given quadrature point
526 baseSet.jacobianAll( quadrature[ pt ], dphi );
527
528 // get value for linearization
529 RangeType u0;
530 JacobianRangeType jacU0;
531 uLocal.evaluate( quadrature[ pt ], u0 );
532 uLocal.jacobian( quadrature[ pt ], jacU0 );
533
534 RangeType aphi( 0 );
535 JacobianRangeType adphi( 0 );
536 for( unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol )
537 {
538 // if mass terms or right hand side is present
539 model().linSource( u0, jacU0, quadrature[ pt ], phi[ localCol ], dphi[ localCol ], aphi );
540
541 // if gradient term is present
542 model().linFlux( u0, jacU0, quadrature[ pt ], phi[ localCol ], dphi[ localCol ], adphi );
543
544 // get column object and call axpy method
545 jLocal.column( localCol ).axpy( phi, dphi, aphi, adphi, weight );
546 }
547 }
548 if ( rangeSpace.continuous() )
549 {
550 jOp.addLocalMatrix( entity, entity, jLocal );
551 jLocal.unbind();
552 continue;
553 }
554
555 double area = geometry.volume();
556 const IntersectionIteratorType endiit = gridPart.iend( entity );
557 for ( IntersectionIteratorType iit = gridPart.ibegin( entity );
558 iit != endiit ; ++ iit )
559 {
560 const IntersectionType& intersection = *iit ;
561
562 if( intersection.neighbor() )
563 {
564 const EntityType neighbor = intersection.outside() ;
565
566 typedef typename IntersectionType::Geometry IntersectionGeometryType;
567 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
568
570 // get local matrix for face entries
571 localOpNb.bind( neighbor, entity );
572 localOpNb.clear();
573
574 // get neighbor's base function set
575 const BasisFunctionSetType &baseSetNb = localOpNb.domainBasisFunctionSet();
577
578 // compute penalty factor
579 const double intersectionArea = intersectionGeometry.volume();
580 const double beta = penalty()(intersection,intersectionArea,area,neighbor.geometry().volume());
581
582 // here we assume that the intersection is conforming
583 FaceQuadratureType faceQuadInside(gridPart, intersection, 2*rangeSpace.order() + 1,
584 FaceQuadratureType::INSIDE);
585 FaceQuadratureType faceQuadOutside(gridPart, intersection, 2*rangeSpace.order() + 1,
586 FaceQuadratureType::OUTSIDE);
587
588 const size_t numFaceQuadPoints = faceQuadInside.nop();
589 for( size_t pt = 0; pt < numFaceQuadPoints; ++pt )
590 {
591 const typename FaceQuadratureType::LocalCoordinateType &x = faceQuadInside.localPoint( pt );
592 DomainType normal = intersection.integrationOuterNormal( x );
593 double faceVol = normal.two_norm();
594 normal /= faceVol; // make it into a unit normal
595
596 const double quadWeight = faceQuadInside.weight( pt );
597 const double weight = quadWeight * faceVol;
598
600 RangeType u0En;
601 JacobianRangeType u0EnJac;
602 uLocal.evaluate( faceQuadInside[ pt ], u0En );
603 uLocal.jacobian( faceQuadInside[ pt ], u0EnJac );
604
606 // evaluate basis function of face inside E^- (entity)
608
609 // evaluate all basis functions for quadrature point pt
610 baseSet.evaluateAll( faceQuadInside[ pt ], phi );
611
612 // evaluate the jacobians of all basis functions
613 baseSet.jacobianAll( faceQuadInside[ pt ], dphi );
614
616 // evaluate basis function of face inside E^+ (neighbor)
618
619 // evaluate all basis functions for quadrature point pt on neighbor
620 baseSetNb.evaluateAll( faceQuadOutside[ pt ], phiNb );
621
622 // evaluate the jacobians of all basis functions on neighbor
623 baseSetNb.jacobianAll( faceQuadOutside[ pt ], dphiNb );
624
625 model().init( entity );
626 for( unsigned int i = 0; i < numBaseFunctions; ++i )
627 {
628 JacobianRangeType adphiEn = dphi[ i ];
629 model().linFlux( u0En, u0EnJac, faceQuadInside[ pt ], phi[i], adphiEn, dphi[ i ] );
630 }
631 auto pFactor = model().penalty( faceQuadInside[ pt ], u0En );
632 model().init( neighbor );
633 for( unsigned int i = 0; i < numBaseFunctions; ++i )
634 {
635 JacobianRangeType adphiNb = dphiNb[ i ];
636 model().linFlux( u0En, u0EnJac, faceQuadOutside[ pt ], phiNb[i], adphiNb, dphiNb[ i ] );
637 }
638 pFactor += model().penalty( faceQuadOutside[ pt ], u0En );
639 model().init( entity );
641
643 for( unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol )
644 {
645 RangeType valueEn(0), valueNb(0);
646 JacobianRangeType dvalueEn(0), dvalueNb(0);
647
648 // -{ A grad u } * [ phi_en ]
649 dphi[localCol].usmv( -0.5, normal, valueEn );
650
651 // -{ A grad u } * [ phi_en ]
652 dphiNb[localCol].usmv( -0.5, normal, valueNb );
653
654 // [ u ] * [ phi_en ] = u^- * phi_en^-
655 for (unsigned int r=0;r<dimRange;++r)
656 {
657 valueEn[r] += beta*pFactor[r]/2.*phi[localCol][r];
658 valueNb[r] -= beta*pFactor[r]/2.*phiNb[localCol][r];
659 }
660 // here we need a diadic product of u x n
661 for ( int r=0; r< dimRange; ++r )
662 for ( int d=0; d< dimDomain; ++d )
663 {
664 // [ u ] * { grad phi_en }
665 dvalueEn[r][d] = - 0.5 * normal[d] * phi[localCol][r];
666
667 // [ u ] * { grad phi_en }
668 dvalueNb[r][d] = 0.5 * normal[d] * phiNb[localCol][r];
669 }
670
671 jLocal.column( localCol ).axpy( phi, dphi, valueEn, dvalueEn, weight );
672 localOpNb.column( localCol ).axpy( phi, dphi, valueNb, dvalueNb, weight );
673 }
674 }
675 jOp.addLocalMatrix( neighbor, entity, localOpNb );
676 localOpNb.unbind();
677 }
678 else if( intersection.boundary() )
679 {
680 std::array<int,dimRange> components;
681 components.fill(0);
682 model().isDirichletIntersection( intersection, components);
683
684 typedef typename IntersectionType::Geometry IntersectionGeometryType;
685 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
686
687 // compute penalty factor
688 const double intersectionArea = intersectionGeometry.volume();
689 const double beta = penalty()(intersection,intersectionArea,area,area);
690
691 // here we assume that the intersection is conforming
692 FaceQuadratureType faceQuadInside(gridPart, intersection, 2*rangeSpace.order() + 1,
693 FaceQuadratureType::INSIDE);
694
695 const size_t numFaceQuadPoints = faceQuadInside.nop();
696 for( size_t pt = 0; pt < numFaceQuadPoints; ++pt )
697 {
698 const typename FaceQuadratureType::LocalCoordinateType &x = faceQuadInside.localPoint( pt );
699 DomainType normal = intersection.integrationOuterNormal( x );
700 double faceVol = normal.two_norm();
701 normal /= faceVol; // make it into a unit normal
702
703 const double quadWeight = faceQuadInside.weight( pt );
704 const double weight = quadWeight * faceVol;
705
706 RangeType u0En;
707 JacobianRangeType u0EnJac;
708 uLocal.evaluate( faceQuadInside[ pt ], u0En );
709 uLocal.jacobian( faceQuadInside[ pt ], u0EnJac );
710
712 // evaluate basis function of face inside E^- (entity)
714
715 // evaluate all basis functions for quadrature point pt
716 baseSet.evaluateAll( faceQuadInside[ pt ], phi );
717
718 // evaluate the jacobians of all basis functions
719 baseSet.jacobianAll( faceQuadInside[ pt ], dphi );
720
721 for( unsigned int i = 0; i < numBaseFunctions; ++i )
722 {
723 JacobianRangeType adphiEn = dphi[ i ];
724 model().linFlux( u0En, u0EnJac, faceQuadInside[ pt ], phi[i], adphiEn, dphi[ i ] );
725 }
726
727 auto pFactor = model().penalty( faceQuadInside[ pt ], u0En );
728
729 for( unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol )
730 {
731 RangeType valueEn(0);
732 JacobianRangeType dvalueEn(0);
733
734 // -{ A grad u } * [ phi_en ]
735 dphi[localCol].usmv( -1.0, normal, valueEn );
736
737 // [ u ] * [ phi_en ] = u^- * phi_en^-
738 for (unsigned int r=0;r<dimRange;++r)
739 valueEn[r] += beta*pFactor[r]*phi[ localCol ][r];
740
741 // here we need a diadic product of u x n
742 for ( int r=0; r< dimRange; ++r )
743 for ( int d=0; d< dimDomain; ++d )
744 {
745 // [ u ] * { grad phi_en }
746 dvalueEn[r][d] = - 0.5 * normal[d] * phi[localCol][r];
747 }
748
749 for (int r=0;r<dimRange;++r)
750 if (!components[r]) // do not use dirichlet constraints here
751 {
752 valueEn[r] = 0;
753 dvalueEn[r] = 0;
754 }
755
756 jLocal.column( localCol ).axpy( phi, dphi, valueEn, dvalueEn, weight );
757 }
758 }
759 } // is boundary
760 } // end of intersection loop
761 jOp.addLocalMatrix( entity, entity, jLocal );
762 jLocal.unbind();
763 } // end grid traversal
764 jOp.flushAssembly();
765 // std::cout << " in assembly: final " << timer.elapsed() << std::endl;;
766}
767
768#endif // ELLIPTIC_HH
Traits::IntersectionIteratorType IntersectionIteratorType
type of intersection iterator
Definition: adaptiveleafgridpart.hh:92
quadrature class supporting base function caching
Definition: cachingquadrature.hh:106
abstract differentiable operator
Definition: differentiableoperator.hh:29
JacobianOperator JacobianOperatorType
type of linear operator modelling the operator's Jacobian
Definition: differentiableoperator.hh:35
virtual void jacobian(const DomainFunctionType &u, JacobianOperatorType &jOp) const =0
obtain linearization
RangeFunctionType::RangeFieldType RangeFieldType
field type of the operator's range
Definition: differentiableoperator.hh:45
GridPartType::template Codim< Traits::codimension >::IteratorType IteratorType
type of iterator for grid traversal
Definition: discretefunctionspace.hh:222
FunctionSpaceType::JacobianRangeType JacobianRangeType
type of the Jacobian, i.e., type of evaluated Jacobian matrix
Definition: localfunction.hh:112
const DomainSpaceType & domainSpace() const
access to the domain space
Definition: localmatrix.hh:382
A local matrix with a small array as storage.
Definition: temporarylocalmatrix.hh:100
forward declaration
Definition: discretefunction.hh:51
TupleDiscreteFunctionSpace< typename DiscreteFunctions::DiscreteFunctionSpaceType ... > DiscreteFunctionSpaceType
type for the discrete function space this function lives in
Definition: discretefunction.hh:69
GeometryType
Type representing VTK's entity geometry types.
Definition: common.hh:132
Implements a matrix constructed from a given type representing a field and compile-time given number ...
Stencil contaning the entries (en,en) and (en,nb) for all entities en in the space and neighbors nb o...
Definition: stencil.hh:387
abstract operator
Definition: operator.hh:34
virtual void operator()(const DomainFunctionType &u, RangeFunctionType &w) const =0
application operator
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 21, 22:33, 2025)