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 {
117 // std::cout << "dg operator with penalty:" << penalty_.factor() << std::endl;
118 }
119
120 DGEllipticOperator ( const DiscreteFunctionSpaceType &dSpace,
121 const DiscreteFunctionSpaceType &rSpace,
122 const ModelType &model,
123 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
124 : model_( model ),
125 penalty_( dSpace, parameter.getValue< double >( "penalty", 40 ) )
126 {
127 // std::cout << "dg operator with penalty:" << penalty_.factor() << std::endl;
128 }
129
131 virtual void operator() ( const DomainDiscreteFunctionType &u, RangeDiscreteFunctionType &w ) const
132 { apply(u,w); }
133 template <class GF>
134 void apply( const GF &u, RangeDiscreteFunctionType &w ) const;
135
136protected:
137 const ModelType &model () const { return model_; }
138 Penalty penalty() const { return penalty_; }
139
140private:
141 const ModelType &model_;
142 Penalty penalty_;
143};
144
145// DifferentiableDGEllipticOperator
146// ------------------------------
147
148template< class JacobianOperator, class Model,
149 class Penalty = DefaultPenalty<typename JacobianOperator::DomainFunctionType::DiscreteFunctionSpaceType > >
150struct DifferentiableDGEllipticOperator
151: public DGEllipticOperator< typename JacobianOperator::DomainFunctionType, Model, Penalty >,
152 public Dune::Fem::DifferentiableOperator< JacobianOperator >
153{
154 typedef DGEllipticOperator< typename JacobianOperator::DomainFunctionType, Model, Penalty > BaseType;
155
156 typedef JacobianOperator JacobianOperatorType;
157
158 typedef typename BaseType::DiscreteFunctionType DiscreteFunctionType;
159 typedef typename BaseType::ModelType ModelType;
160 typedef typename BaseType::DomainDiscreteFunctionType DomainDiscreteFunctionType;
161 typedef typename BaseType::RangeDiscreteFunctionType RangeDiscreteFunctionType;
162
163protected:
164 typedef typename DomainDiscreteFunctionType::DiscreteFunctionSpaceType DomainDiscreteFunctionSpaceType;
165 typedef typename DomainDiscreteFunctionType::LocalFunctionType DomainLocalFunctionType;
166 typedef typename DomainLocalFunctionType::RangeType DomainRangeType;
167 typedef typename DomainLocalFunctionType::JacobianRangeType DomainJacobianRangeType;
168 typedef typename RangeDiscreteFunctionType::DiscreteFunctionSpaceType RangeDiscreteFunctionSpaceType;
169 typedef typename RangeDiscreteFunctionType::LocalFunctionType RangeLocalFunctionType;
170 typedef typename RangeLocalFunctionType::RangeType RangeRangeType;
171 typedef typename RangeLocalFunctionType::JacobianRangeType RangeJacobianRangeType;
172
173 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
174 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
175 typedef typename LocalFunctionType::RangeType RangeType;
177 typedef typename LocalFunctionType::JacobianRangeType JacobianRangeType;
178
179 typedef typename DiscreteFunctionSpaceType::IteratorType IteratorType;
180 typedef typename IteratorType::Entity EntityType;
181 typedef typename EntityType::Geometry GeometryType;
182
183 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
184
185 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
186 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
187 typedef typename IntersectionIteratorType::Intersection IntersectionType;
188 typedef typename IntersectionType::Geometry IntersectionGeometryType;
189
190 typedef Dune::Fem::ElementQuadrature< GridPartType, 1 > FaceQuadratureType;
192
193 static const int dimDomain = LocalFunctionType::dimDomain;
194 static const int dimRange = LocalFunctionType::dimRange;
195
196public:
198 DifferentiableDGEllipticOperator ( const DiscreteFunctionSpaceType &space,
199 const ModelType &model,
200 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
201 : BaseType( space, model, parameter )
202 {}
203 DifferentiableDGEllipticOperator ( const DiscreteFunctionSpaceType &dSpace,
204 const DiscreteFunctionSpaceType &rSpace,
205 const ModelType &model,
206 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
207 : BaseType( dSpace, rSpace, model, parameter )
208 {}
209
211 void jacobian ( const DomainDiscreteFunctionType &u, JacobianOperatorType &jOp ) const
212 { apply(u,jOp); }
213 template <class GridFunctionType>
214 void apply ( const GridFunctionType &u, JacobianOperatorType &jOp ) const;
215 using BaseType::apply;
216
217protected:
218 using BaseType::model;
219 using BaseType::penalty;
220};
221
222// Implementation of DGEllipticOperator
223// ----------------------------------
224
225template< class RangeDiscreteFunction, class Model, class Penalty >
226template<class GF>
227void DGEllipticOperator< RangeDiscreteFunction, Model, Penalty >
228 ::apply( const GF &u, RangeDiscreteFunctionType &w ) const
229{
230 // clear destination
231 w.clear();
232
233 // get discrete function space
234 const DiscreteFunctionSpaceType &dfSpace = w.space();
235 Dune::Fem::ConstLocalFunction< GF > uLocal( u );
236 Dune::Fem::ConstLocalFunction< GF > uOutLocal( u );
237 Dune::Fem::AddLocalContribution< RangeDiscreteFunctionType > wLocal( w );
238
239 // iterate over grid
240 const IteratorType end = dfSpace.end();
241 for( IteratorType it = dfSpace.begin(); it != end; ++it )
242 {
243 // get entity (here element)
244 const EntityType &entity = *it;
245
246 bool needsCalculation = model().init( entity );
247 if (! needsCalculation )
248 continue;
249
250 // get elements geometry
251 const GeometryType &geometry = entity.geometry();
252
253 // get local representation of the discrete functions
254 auto uGuard = Dune::Fem::bindGuard( uLocal, entity );
255 auto wGuard = Dune::Fem::bindGuard( wLocal, entity );
256
257 // obtain quadrature order
258 const int quadOrder = uLocal.order() + wLocal.order();
259
260 { // element integral
261 QuadratureType quadrature( entity, quadOrder );
262 const size_t numQuadraturePoints = quadrature.nop();
263 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
264 {
265 const typename QuadratureType::CoordinateType &x = quadrature.point( pt );
266 const double weight = quadrature.weight( pt ) * geometry.integrationElement( x );
267
268 RangeType vu;
269 uLocal.evaluate( quadrature[ pt ], vu );
270 JacobianRangeType du;
271 uLocal.jacobian( quadrature[ pt ], du );
272
273 // compute mass contribution (studying linear case so linearizing around zero)
274 RangeType avu( 0 );
275 model().source( quadrature[ pt ], vu, du, avu );
276 avu *= weight;
277 // add to local functional wLocal.axpy( quadrature[ pt ], avu );
278
279 JacobianRangeType adu( 0 );
280 // apply diffusive flux
281 model().flux( quadrature[ pt ], vu, du, adu );
282 adu *= weight;
283
284 // add to local function
285 wLocal.axpy( quadrature[ pt ], avu, adu );
286 }
287 }
288 if ( ! dfSpace.continuous() )
289 {
290 const double area = entity.geometry().volume();
291 const IntersectionIteratorType iitend = dfSpace.gridPart().iend( entity );
292 for( IntersectionIteratorType iit = dfSpace.gridPart().ibegin( entity ); iit != iitend; ++iit ) // looping over intersections
293 {
295 const IntersectionType &intersection = *iit;
296 if ( intersection.neighbor() )
297 {
298 const EntityType outside = intersection.outside() ;
299
300 typedef typename IntersectionType::Geometry IntersectionGeometryType;
301 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
302
303 // compute penalty factor
304 const double intersectionArea = intersectionGeometry.volume();
305 const double beta = penalty()(intersection,intersectionArea,area,outside.geometry().volume());
306
307 auto uOutGuard = Dune::Fem::bindGuard( uOutLocal, outside );
308
309 FaceQuadratureType quadInside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::INSIDE );
310 FaceQuadratureType quadOutside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::OUTSIDE );
311 const size_t numQuadraturePoints = quadInside.nop();
313
314 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
315 {
317 // get coordinate of quadrature point on the reference element of the intersection
318 const typename FaceQuadratureType::LocalCoordinateType &x = quadInside.localPoint( pt );
319 DomainType normal = intersection.integrationOuterNormal( x );
320 double faceVol = normal.two_norm();
321 normal /= faceVol; // make it into a unit normal
322 const double weight = quadInside.weight( pt ) * faceVol;
323
324 RangeType vuIn,vuOut;
325 JacobianRangeType duIn, duOut;
326 uLocal.evaluate( quadInside[ pt ], vuIn );
327 uLocal.jacobian( quadInside[ pt ], duIn );
328 uOutLocal.evaluate( quadOutside[ pt ], vuOut );
329 uOutLocal.jacobian( quadOutside[ pt ], duOut );
330 RangeType jump = vuIn - vuOut;
331 // compute -0.5 * [u] x normal
332 JacobianRangeType dvalue;
333 for (int r=0;r<dimRange;++r)
334 for (int d=0;d<dimDomain;++d)
335 dvalue[r][d] = -0.5 * normal[d] * jump[r];
336 JacobianRangeType aduIn,aduOut;
337 model().init( outside );
338 model().flux( quadOutside[ pt ], vuOut, duOut, aduOut );
339 auto pFactor = model().penalty( quadOutside[ pt ], vuOut );
340 model().init( entity );
341 model().flux( quadInside[ pt ], vuIn, duIn, aduIn );
342 JacobianRangeType affine;
343 model().flux( quadInside[ pt ], RangeType(0), JacobianRangeType(0), affine);
344 pFactor += model().penalty( quadInside[ pt ], vuIn );
346
348 RangeType value;
349 JacobianRangeType advalue;
350 // penalty term : beta [u] [phi] = beta (u+ - u-)(phi+ - phi-)=beta (u+ - u-)phi+
351 value = jump;
352 for (unsigned int r=0;r<dimRange;++r)
353 value[r] *= beta * pFactor[r]/2.;
354 // {A grad u}.[phi] = {A grad u}.phi+ n_+ = 0.5*(grad u+ + grad u-).n_+ phi+
355 aduIn += aduOut;
356 aduIn *= -0.5;
357 aduIn.umv(normal,value);
358 // [ u ] * { {A} grad phi_en } = -normal(u+ - u-) * 0.5 {A} grad phi_en
359 // we actually need G(u)tau with G(x,u) = d/sigma_j D_i(x,u,sigma)
360 // - we might need to assume D(x,u,sigma) = G(x,u)sigma + affine(x)
361 model().flux( quadInside[ pt ], vuIn, dvalue, advalue );
362 // advalue -= affine;
363
364 value *= weight;
365 advalue *= weight;
366 wLocal.axpy( quadInside[ pt ], value, advalue );
368 }
369 }
370 else if( intersection.boundary() )
371 {
372 std::array<int,dimRange> components;
373 components.fill(0);
374 model().isDirichletIntersection( intersection, components);
375
376 typedef typename IntersectionType::Geometry IntersectionGeometryType;
377 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
378
379 // compute penalty factor
380 const double intersectionArea = intersectionGeometry.volume();
381 const double beta = penalty()(intersection,intersectionArea,area,area);
382
383 FaceQuadratureType quadInside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::INSIDE );
384 const size_t numQuadraturePoints = quadInside.nop();
385
386 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
387 {
388 const typename FaceQuadratureType::LocalCoordinateType &x = quadInside.localPoint( pt );
389 const DomainType normal = intersection.integrationOuterNormal( x );
390 const double weight = quadInside.weight( pt );
391
392 RangeType bndValue;
393 model().dirichlet(1, quadInside[pt], bndValue);
394
395 RangeType value;
396 JacobianRangeType dvalue,advalue;
397
398 RangeType vuIn,jump;
399 JacobianRangeType duIn, aduIn;
400 uLocal.evaluate( quadInside[ pt ], vuIn );
401 uLocal.jacobian( quadInside[ pt ], duIn );
402 jump = vuIn;
403 jump -= bndValue;
404
405 // penalty term : beta [u] [phi] = beta (u+ - u-)(phi+ - phi-)=beta (u+ - u-)phi+
406 auto pFactor = model().penalty( quadInside[ pt ], vuIn );
407 value = jump;
408 for (unsigned int r=0;r<dimRange;++r)
409 value[r] *= beta * pFactor[r] * intersectionGeometry.integrationElement( x );
410
411 // [ u ] * { grad phi_en } = -normal(u+ - u-) * 0.5 grad phi_en
412 // here we need a diadic product of u x n
413 for (int r=0;r<dimRange;++r)
414 for (int d=0;d<dimDomain;++d)
415 dvalue[r][d] = -0.5 * normal[d] * jump[r];
416
417 model().flux( quadInside[ pt ], jump, dvalue, advalue );
418
419 // consistency term
420 // {A grad u}.[phi] = {A grad u}.phi+ n_+ = 0.5*(grad u+ + grad u-).n_+ phi+
421 model().flux( quadInside[ pt ], vuIn, duIn, aduIn );
422 aduIn.mmv(normal,value);
423
424 for (int r=0;r<dimRange;++r)
425 if (!components[r]) // do not use dirichlet constraints here
426 {
427 value[r] = 0;
428 advalue[r] = 0;
429 }
430
431 value *= weight;
432 advalue *= weight;
433 wLocal.axpy( quadInside[ pt ], value, advalue );
434 }
435 }
436 }
437 }
438
439 }
440
441 // communicate data (in parallel runs)
442 w.communicate();
443}
444
445// Implementation of DifferentiableDGEllipticOperator
446// ------------------------------------------------
447template< class JacobianOperator, class Model, class Penalty >
448template<class GF>
449void DifferentiableDGEllipticOperator< JacobianOperator, Model, Penalty >
450 ::apply ( const GF &u, JacobianOperator &jOp ) const
451{
452 // std::cout << "starting assembly\n";
453 // Dune::Timer timer;
454 typedef typename DiscreteFunctionSpaceType::BasisFunctionSetType BasisFunctionSetType;
456
457 const DomainDiscreteFunctionSpaceType &domainSpace = jOp.domainSpace();
458 const RangeDiscreteFunctionSpaceType &rangeSpace = jOp.rangeSpace();
459
461 jOp.reserve(stencil);
462 jOp.clear();
463
464 Dune::Fem::ConstLocalFunction< GF > uLocal( u );
465 TmpLocalMatrixType jLocal( domainSpace, rangeSpace );
466 TmpLocalMatrixType localOpNb( domainSpace, rangeSpace );
467
468 const GridPartType& gridPart = rangeSpace.gridPart();
469
470 const unsigned int numDofs = rangeSpace.blockMapper().maxNumDofs() *
471 DiscreteFunctionSpaceType :: localBlockSize ;
472
473 std::vector< RangeType > phi( numDofs );
474 std::vector< JacobianRangeType > dphi( numDofs );
475
476 std::vector< RangeType > phiNb( numDofs );
477 std::vector< JacobianRangeType > dphiNb( numDofs );
478
479 // std::cout << " in assembly: start element loop size=" << rangeSpace.gridPart().grid().size(0) << " time= " << timer.elapsed() << std::endl;;
480 const IteratorType end = rangeSpace.end();
481 for( IteratorType it = rangeSpace.begin(); it != end; ++it )
482 {
483 const EntityType &entity = *it;
484
485 bool needsCalculation = model().init( entity );
486 if (! needsCalculation )
487 continue;
488
489 const GeometryType geometry = entity.geometry();
490
491 auto uGuard = Dune::Fem::bindGuard( uLocal, entity );
492
493 jLocal.bind( entity, entity );
494 jLocal.clear();
495
496 const BasisFunctionSetType &baseSet = jLocal.domainBasisFunctionSet();
497 const unsigned int numBaseFunctions = baseSet.size();
498
499 QuadratureType quadrature( entity, 2*rangeSpace.order() );
500 const size_t numQuadraturePoints = quadrature.nop();
501 for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
502 {
503 const typename QuadratureType::CoordinateType &x = quadrature.point( pt );
504 const double weight = quadrature.weight( pt ) * geometry.integrationElement( x );
505
506 // evaluate all basis functions at given quadrature point
507 baseSet.evaluateAll( quadrature[ pt ], phi );
508
509 // evaluate jacobians of all basis functions at given quadrature point
510 baseSet.jacobianAll( quadrature[ pt ], dphi );
511
512 // get value for linearization
513 RangeType u0;
514 JacobianRangeType jacU0;
515 uLocal.evaluate( quadrature[ pt ], u0 );
516 uLocal.jacobian( quadrature[ pt ], jacU0 );
517
518 RangeType aphi( 0 );
519 JacobianRangeType adphi( 0 );
520 for( unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol )
521 {
522 // if mass terms or right hand side is present
523 model().linSource( u0, jacU0, quadrature[ pt ], phi[ localCol ], dphi[ localCol ], aphi );
524
525 // if gradient term is present
526 model().linFlux( u0, jacU0, quadrature[ pt ], phi[ localCol ], dphi[ localCol ], adphi );
527
528 // get column object and call axpy method
529 jLocal.column( localCol ).axpy( phi, dphi, aphi, adphi, weight );
530 }
531 }
532 if ( rangeSpace.continuous() )
533 {
534 jOp.addLocalMatrix( entity, entity, jLocal );
535 jLocal.unbind();
536 continue;
537 }
538
539 double area = geometry.volume();
540 const IntersectionIteratorType endiit = gridPart.iend( entity );
541 for ( IntersectionIteratorType iit = gridPart.ibegin( entity );
542 iit != endiit ; ++ iit )
543 {
544 const IntersectionType& intersection = *iit ;
545
546 if( intersection.neighbor() )
547 {
548 const EntityType neighbor = intersection.outside() ;
549
550 typedef typename IntersectionType::Geometry IntersectionGeometryType;
551 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
552
554 // get local matrix for face entries
555 localOpNb.bind( neighbor, entity );
556 localOpNb.clear();
557
558 // get neighbor's base function set
559 const BasisFunctionSetType &baseSetNb = localOpNb.domainBasisFunctionSet();
561
562 // compute penalty factor
563 const double intersectionArea = intersectionGeometry.volume();
564 const double beta = penalty()(intersection,intersectionArea,area,neighbor.geometry().volume());
565
566 // here we assume that the intersection is conforming
567 FaceQuadratureType faceQuadInside(gridPart, intersection, 2*rangeSpace.order() + 1,
568 FaceQuadratureType::INSIDE);
569 FaceQuadratureType faceQuadOutside(gridPart, intersection, 2*rangeSpace.order() + 1,
570 FaceQuadratureType::OUTSIDE);
571
572 const size_t numFaceQuadPoints = faceQuadInside.nop();
573 for( size_t pt = 0; pt < numFaceQuadPoints; ++pt )
574 {
575 const typename FaceQuadratureType::LocalCoordinateType &x = faceQuadInside.localPoint( pt );
576 DomainType normal = intersection.integrationOuterNormal( x );
577 double faceVol = normal.two_norm();
578 normal /= faceVol; // make it into a unit normal
579
580 const double quadWeight = faceQuadInside.weight( pt );
581 const double weight = quadWeight * faceVol;
582
584 RangeType u0En;
585 JacobianRangeType u0EnJac;
586 uLocal.evaluate( faceQuadInside[ pt ], u0En );
587 uLocal.jacobian( faceQuadInside[ pt ], u0EnJac );
588
590 // evaluate basis function of face inside E^- (entity)
592
593 // evaluate all basis functions for quadrature point pt
594 baseSet.evaluateAll( faceQuadInside[ pt ], phi );
595
596 // evaluate the jacobians of all basis functions
597 baseSet.jacobianAll( faceQuadInside[ pt ], dphi );
598
600 // evaluate basis function of face inside E^+ (neighbor)
602
603 // evaluate all basis functions for quadrature point pt on neighbor
604 baseSetNb.evaluateAll( faceQuadOutside[ pt ], phiNb );
605
606 // evaluate the jacobians of all basis functions on neighbor
607 baseSetNb.jacobianAll( faceQuadOutside[ pt ], dphiNb );
608
609 model().init( entity );
610 for( unsigned int i = 0; i < numBaseFunctions; ++i )
611 {
612 JacobianRangeType adphiEn = dphi[ i ];
613 model().linFlux( u0En, u0EnJac, faceQuadInside[ pt ], phi[i], adphiEn, dphi[ i ] );
614 }
615 auto pFactor = model().penalty( faceQuadInside[ pt ], u0En );
616 model().init( neighbor );
617 for( unsigned int i = 0; i < numBaseFunctions; ++i )
618 {
619 JacobianRangeType adphiNb = dphiNb[ i ];
620 model().linFlux( u0En, u0EnJac, faceQuadOutside[ pt ], phiNb[i], adphiNb, dphiNb[ i ] );
621 }
622 pFactor += model().penalty( faceQuadOutside[ pt ], u0En );
623 model().init( entity );
625
627 for( unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol )
628 {
629 RangeType valueEn(0), valueNb(0);
630 JacobianRangeType dvalueEn(0), dvalueNb(0);
631
632 // -{ A grad u } * [ phi_en ]
633 dphi[localCol].usmv( -0.5, normal, valueEn );
634
635 // -{ A grad u } * [ phi_en ]
636 dphiNb[localCol].usmv( -0.5, normal, valueNb );
637
638 // [ u ] * [ phi_en ] = u^- * phi_en^-
639 for (unsigned int r=0;r<dimRange;++r)
640 {
641 valueEn[r] += beta*pFactor[r]/2.*phi[localCol][r];
642 valueNb[r] -= beta*pFactor[r]/2.*phiNb[localCol][r];
643 }
644 // here we need a diadic product of u x n
645 for ( int r=0; r< dimRange; ++r )
646 for ( int d=0; d< dimDomain; ++d )
647 {
648 // [ u ] * { grad phi_en }
649 dvalueEn[r][d] = - 0.5 * normal[d] * phi[localCol][r];
650
651 // [ u ] * { grad phi_en }
652 dvalueNb[r][d] = 0.5 * normal[d] * phiNb[localCol][r];
653 }
654
655 jLocal.column( localCol ).axpy( phi, dphi, valueEn, dvalueEn, weight );
656 localOpNb.column( localCol ).axpy( phi, dphi, valueNb, dvalueNb, weight );
657 }
658 }
659 jOp.addLocalMatrix( neighbor, entity, localOpNb );
660 localOpNb.unbind();
661 }
662 else if( intersection.boundary() )
663 {
664 std::array<int,dimRange> components;
665 components.fill(0);
666 model().isDirichletIntersection( intersection, components);
667
668 typedef typename IntersectionType::Geometry IntersectionGeometryType;
669 const IntersectionGeometryType &intersectionGeometry = intersection.geometry();
670
671 // compute penalty factor
672 const double intersectionArea = intersectionGeometry.volume();
673 const double beta = penalty()(intersection,intersectionArea,area,area);
674
675 // here we assume that the intersection is conforming
676 FaceQuadratureType faceQuadInside(gridPart, intersection, 2*rangeSpace.order() + 1,
677 FaceQuadratureType::INSIDE);
678
679 const size_t numFaceQuadPoints = faceQuadInside.nop();
680 for( size_t pt = 0; pt < numFaceQuadPoints; ++pt )
681 {
682 const typename FaceQuadratureType::LocalCoordinateType &x = faceQuadInside.localPoint( pt );
683 DomainType normal = intersection.integrationOuterNormal( x );
684 double faceVol = normal.two_norm();
685 normal /= faceVol; // make it into a unit normal
686
687 const double quadWeight = faceQuadInside.weight( pt );
688 const double weight = quadWeight * faceVol;
689
690 RangeType u0En;
691 JacobianRangeType u0EnJac;
692 uLocal.evaluate( faceQuadInside[ pt ], u0En );
693 uLocal.jacobian( faceQuadInside[ pt ], u0EnJac );
694
696 // evaluate basis function of face inside E^- (entity)
698
699 // evaluate all basis functions for quadrature point pt
700 baseSet.evaluateAll( faceQuadInside[ pt ], phi );
701
702 // evaluate the jacobians of all basis functions
703 baseSet.jacobianAll( faceQuadInside[ pt ], dphi );
704
705 for( unsigned int i = 0; i < numBaseFunctions; ++i )
706 {
707 JacobianRangeType adphiEn = dphi[ i ];
708 model().linFlux( u0En, u0EnJac, faceQuadInside[ pt ], phi[i], adphiEn, dphi[ i ] );
709 }
710
711 auto pFactor = model().penalty( faceQuadInside[ pt ], u0En );
712
713 for( unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol )
714 {
715 RangeType valueEn(0);
716 JacobianRangeType dvalueEn(0);
717
718 // -{ A grad u } * [ phi_en ]
719 dphi[localCol].usmv( -1.0, normal, valueEn );
720
721 // [ u ] * [ phi_en ] = u^- * phi_en^-
722 for (unsigned int r=0;r<dimRange;++r)
723 valueEn[r] += beta*pFactor[r]*phi[ localCol ][r];
724
725 // here we need a diadic product of u x n
726 for ( int r=0; r< dimRange; ++r )
727 for ( int d=0; d< dimDomain; ++d )
728 {
729 // [ u ] * { grad phi_en }
730 dvalueEn[r][d] = - 0.5 * normal[d] * phi[localCol][r];
731 }
732
733 for (int r=0;r<dimRange;++r)
734 if (!components[r]) // do not use dirichlet constraints here
735 {
736 valueEn[r] = 0;
737 dvalueEn[r] = 0;
738 }
739
740 jLocal.column( localCol ).axpy( phi, dphi, valueEn, dvalueEn, weight );
741 }
742 }
743 } // is boundary
744 } // end of intersection loop
745 jOp.addLocalMatrix( entity, entity, jLocal );
746 jLocal.unbind();
747 } // end grid traversal
748 jOp.flushAssembly();
749 // std::cout << " in assembly: final " << timer.elapsed() << std::endl;;
750}
751
752#endif // ELLIPTIC_HH
Traits::IntersectionIteratorType IntersectionIteratorType
type of intersection iterator
Definition: adaptiveleafgridpart.hh:92
quadrature class supporting base function caching
Definition: cachingquadrature.hh:101
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  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)