DUNE-FEM (unstable)

localmassmatrix.hh
1#ifndef DUNE_FEM_LOCALMASSMATRIX_HH
2#define DUNE_FEM_LOCALMASSMATRIX_HH
3
4//- dune-common includes
7
8//- dune-geometry includes
10
11//- dune-fem includes
12#include <dune/fem/common/memory.hh>
13#include <dune/fem/common/utility.hh>
14#include <dune/fem/misc/checkgeomaffinity.hh>
15#include <dune/fem/quadrature/cachingquadrature.hh>
16#include <dune/fem/space/common/allgeomtypes.hh>
17#include <dune/fem/space/common/capabilities.hh>
18#include <dune/fem/version.hh>
19
20namespace Dune
21{
22
23 namespace Fem
24 {
25
32 template< class DiscreteFunctionSpace, class VolumeQuadrature, bool refElemScaling = true >
34 {
36
37 public:
39 typedef typename DiscreteFunctionSpaceType :: RangeFieldType ctype;
40 typedef typename DiscreteFunctionSpaceType :: RangeFieldType RangeFieldType;
41 typedef typename DiscreteFunctionSpaceType :: RangeType RangeType;
42
43 enum { dimRange = DiscreteFunctionSpaceType :: dimRange };
44 enum { localBlockSize = DiscreteFunctionSpaceType :: localBlockSize };
45 enum { dgNumDofs = localBlockSize };
46
49
50 typedef typename DiscreteFunctionSpaceType :: GridPartType GridPartType;
51
52 typedef typename DiscreteFunctionSpaceType :: IndexSetType IndexSetType;
53 typedef typename IndexSetType :: IndexType IndexType;
54
55 typedef typename DiscreteFunctionSpaceType :: BasisFunctionSetType BasisFunctionSetType;
56
57 typedef typename GridPartType :: GridType GridType;
58 typedef typename DiscreteFunctionSpaceType :: EntityType EntityType;
59 typedef typename EntityType :: Geometry Geometry;
60
61 typedef VolumeQuadrature VolumeQuadratureType;
62
64
66 enum { StructuredGrid = Dune::Capabilities::isCartesian< GridType >::v };
67
70
71 // use dynamic matrix from dune-common
74
75 protected:
76 std::shared_ptr< const DiscreteFunctionSpaceType > spc_;
77 const IndexSetType& indexSet_;
78
80 const std::function<int(const int)> volumeQuadratureOrder_;
81 const bool affine_;
82
83 mutable DGMatrixType dgMatrix_;
84 mutable DGVectorType dgX_, dgRhs_;
85
86 // use dynamic vector from dune-common
87
88 mutable VectorType rhs_, row_;
89 mutable MatrixType matrix_;
90
91 mutable std::vector< RangeType > phi_;
92 mutable std::vector< RangeType > phiMass_;
93
94 typedef std::pair< std::unique_ptr< MatrixType >, std::unique_ptr< VectorType > > MatrixPairType;
95 typedef std::map< const int, MatrixPairType > MassMatrixStorageType;
96 typedef std::vector< MassMatrixStorageType > LocalInverseMassMatrixStorageType;
97
98 mutable LocalInverseMassMatrixStorageType localInverseMassMatrix_;
99
100 // index of entity from index set, don't setup mass matrix for the same entity twice
101 mutable IndexType lastEntityIndex_;
102 mutable unsigned int lastTopologyId_ ;
103 // sequence number (obtained from DofManager via the space)
104 mutable int sequence_;
105
106 struct NoMassDummyCaller
107 {
109
110 // return false since we don;t have a mass term
111 bool hasMass () const { return false; }
112
113 void mass ( const EntityType &, const VolumeQuadratureType &, int, MassFactorType & ) const
114 {}
115 };
116
117
118 bool checkDiagonalMatrix( const MatrixType& matrix ) const
119 {
120 const int rows = matrix.rows();
121 for( int r=0; r<rows; ++r )
122 {
123 for( int c=0; c<r; ++c ) // the mass matrix is symmetric
124 {
125 // if we find one off diagonal non-zero return false
126 if( std::abs(matrix[r][c]) > 1e-12 )
127 return false;
128 }
129 }
130 return true;
131 }
132
133 template< class BasisFunctionSet >
134 MatrixPairType&
135 getLocalInverseMassMatrix ( const EntityType &entity, const Geometry &geo,
136 const BasisFunctionSet &basisSet, int numBasisFct ) const
137 {
138 const GeometryType geomType = geo.type();
139 typedef typename MassMatrixStorageType::iterator iterator;
140 MassMatrixStorageType &massMap = localInverseMassMatrix_[ GlobalGeometryTypeIndex::index( geomType ) ];
141
142 auto it = massMap.find( numBasisFct );
143 if( it == massMap.end() )
144 {
145 std::pair< iterator, bool > insertPair = massMap.insert( std::make_pair( numBasisFct, MatrixPairType(nullptr,nullptr) ) );
146 it = insertPair.first;
147 insertPair.first->second.first.reset( new MatrixType( numBasisFct, numBasisFct, 0.0 ));
148 MatrixType& matrix = insertPair.first->second.first.operator *();
149 VolumeQuadratureType volQuad( entity, volumeQuadratureOrder( entity ) );
150 buildMatrixNoMassFactor( entity, geo, basisSet, volQuad, numBasisFct, matrix, false );
151 try {
152 matrix.invert();
153 }
154 catch ( Dune::FMatrixError &e )
155 {
156 std::cerr << "Matrix is singular:" << std::endl << matrix << std::endl;
157 std::terminate();
158 }
159 const bool diagonal = checkDiagonalMatrix( matrix );
160 // store diagonal if matrix is diagonal
161 if( diagonal )
162 {
163 insertPair.first->second.second.reset( new VectorType( matrix.rows() ) );
164 VectorType& diag = insertPair.first->second.second.operator *();
165 const int rows = matrix.rows();
166 for( int row=0; row<rows; ++row )
167 {
168 diag[ row ] = matrix[ row ][ row ];
169 }
170 }
171 }
172
173 return it->second;
174 }
175
176 template< class MassCaller, class BasisFunctionSet >
177 MatrixType &getLocalInverseMassMatrixDefault ( MassCaller &caller, const EntityType &entity,
178 const Geometry &geo, const BasisFunctionSet &basisSet ) const
179 {
180 const int numDofs = basisSet.size();
181 // if sequence changed or entity index changed: recompute mass matrix
182 if( entityHasChanged( entity ) || (numDofs != int( matrix_.rows())) )
183 {
184 // resize temporary memory if necessary
185 if( numDofs != int( matrix_.rows() ) )
186 matrix_.resize( numDofs, numDofs );
187
188 buildMatrix( caller, entity, geo, basisSet, numDofs, matrix_ );
189 matrix_.invert();
190 }
191
192 // make sure that rhs_ has the correct size
193 assert( numDofs == int( matrix_.rows() ) );
194 return matrix_;
195 }
196
197 // return number of max non blocked dofs
198 int maxNumDofs () const
199 {
200 return space().blockMapper().maxNumDofs() * localBlockSize;
201 }
202
205 {
206 return volumeQuadratureOrder_( space().order() );
207 }
208
209 public:
211 int volumeQuadratureOrder ( const EntityType &entity ) const
212 {
213 return volumeQuadratureOrder_( space().order( entity ) );
214 }
215
217 explicit LocalMassMatrixImplementation ( const DiscreteFunctionSpaceType &spc, int volQuadOrd )
218 : LocalMassMatrixImplementation( spc, [volQuadOrd](const int order) { return volQuadOrd; } )
219 {}
220
223 std::function<int(const int)> volQuadOrderFct = [](const int order) { return Capabilities::DefaultQuadrature< DiscreteFunctionSpaceType >::volumeOrder(order); } )
224 : spc_( referenceToSharedPtr( spc ) )
225 , indexSet_( space().indexSet() )
226 , geoInfo_( indexSet_ )
227 , volumeQuadratureOrder_ ( volQuadOrderFct )
228 , affine_ ( setup() )
229 , rhs_(), row_(), matrix_()
230 , phi_( maxNumDofs() )
231 , phiMass_( maxNumDofs() )
232 , localInverseMassMatrix_( GlobalGeometryTypeIndex :: size( GridType::dimension ) )
233 , lastEntityIndex_( -1 )
234 , lastTopologyId_( ~0u )
235 , sequence_( -1 )
236 {}
237
240 : spc_(other.spc_),
241 indexSet_( space().indexSet() ),
242 geoInfo_( indexSet_ ),
243 volumeQuadratureOrder_( other.volumeQuadratureOrder_ ),
244 affine_( other.affine_ ),
245 rhs_( other.rhs_ ), row_( other.row_ ), matrix_( other.matrix_ ),
246 phi_( other.phi_ ),
247 phiMass_( other.phiMass_ ),
248 localInverseMassMatrix_( GlobalGeometryTypeIndex :: size( GridType::dimension ) ),
249 lastEntityIndex_( other.lastEntityIndex_ ),
250 lastTopologyId_( other.lastTopologyId_ ),
251 sequence_( other.sequence_ )
252 {}
253
254 public:
256 bool affine () const { return affine_; }
257
259 double getAffineMassFactor(const Geometry& geo) const
260 {
261 // for all normalized spaces scaling with reference element volume
262 // is needed (DG spaces)
263 if constexpr( refElemScaling )
264 {
265 return geoInfo_.referenceVolume( geo.type() ) / geo.volume();
266 }
267 else
268 {
269 // no scaling is needed for finite volume spaces
270 return 1.0 / geo.volume();
271 }
272 }
273
274 template< class BasisFunctionSet >
275 bool checkInterpolationBFS(const BasisFunctionSet &bfs) const
276 {
277 static const int quadPointSetId = SelectQuadraturePointSetId< VolumeQuadratureType >::value;
278 // if BasisFunctionSet does not have an static int member called pointSetId then this will be -1
279 static const int basePointSetId = detail::SelectPointSetId< BasisFunctionSet >::value;
280 // for Lagrange-type basis evaluated on interpolation points
281 // this is the Kronecker delta, so the mass matrix is diagonal even
282 // on non affine grids
283 if constexpr ( quadPointSetId == basePointSetId )
284 {
285 const unsigned int numShapeFunctions = bfs.size() / dimRange;
286 return VolumeQuadratureType( bfs.entity(), volumeQuadratureOrder( bfs.entity() ) )
287 .isInterpolationQuadrature(numShapeFunctions);
288 }
289 return false;
290 }
291
294 template< class MassCaller, class BasisFunctionSet, class LocalFunction >
295 void applyInverse ( MassCaller &caller, const EntityType &entity, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf ) const
296 {
297 Geometry geo = entity.geometry();
298 if( ( affine() || geo.affine() || checkInterpolationBFS(basisFunctionSet) )
299 && !caller.hasMass() )
300 applyInverseLocally( entity, geo, basisFunctionSet, lf );
301 else
302 applyInverseDefault( caller, entity, geo, basisFunctionSet, lf );
303 }
304
307 template< class MassCaller, class LocalFunction >
308 void applyInverse ( MassCaller &caller, const EntityType &entity, LocalFunction &lf ) const
309 {
310 applyInverse( caller, entity, lf.basisFunctionSet(), lf );
311 }
312
314 template< class LocalFunction >
315 void applyInverse ( const EntityType &entity, LocalFunction &lf ) const
316 {
317 NoMassDummyCaller caller;
318 applyInverse( caller, entity, lf.basisFunctionSet(), lf );
319 }
320 template< class BasisFunctionSet, class LocalFunction >
321 void applyInverse ( const EntityType &entity, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf ) const
322 {
323 NoMassDummyCaller caller;
324 applyInverse( caller, entity, basisFunctionSet, lf );
325 }
326
327
329 template< class LocalFunction >
330 void applyInverse ( LocalFunction &lf ) const
331 {
332 applyInverse( lf.entity(), lf );
333 }
334
336 template< class LocalMatrix >
337 void rightMultiplyInverse ( LocalMatrix &localMatrix ) const
338 {
339 const EntityType &entity = localMatrix.rangeEntity();
340 Geometry geo = entity.geometry();
341 if( ( affine() || geo.affine() || checkInterpolationBFS(localMatrix.rangeBasisFunctionSet())) )
342 rightMultiplyInverseLocally( entity, geo, localMatrix );
343 else
344 rightMultiplyInverseDefault( entity, geo, localMatrix );
345 }
346
348 template< class LocalMatrix >
349 void leftMultiplyInverse ( LocalMatrix &localMatrix ) const
350 {
351 const EntityType &entity = localMatrix.domainEntity();
352 Geometry geo = entity.geometry();
353 if( ( affine() || geo.affine() || checkInterpolationBFS(localMatrix.rangeBasisFunctionSet())) )
354 leftMultiplyInverseLocally( entity, geo, localMatrix );
355 else
356 leftMultiplyInverseDefault( entity, geo, localMatrix );
357 }
358
359 const DiscreteFunctionSpaceType &space () const { return *spc_; }
360
362 // end of public methods
364
365 protected:
367 // applyInverse for DG spaces
369 template< class MassCaller, class BasisFunctionSet, class LocalFunction >
370 void applyInverseDgOrthoNormalBasis ( MassCaller &caller, const EntityType &entity,
371 const BasisFunctionSet &basisFunctionSet, LocalFunction &lf ) const
372 {
373 Geometry geo = entity.geometry();
374 assert( dgNumDofs == lf.size() );
375
376 // affine_ can be a static information
377 const bool isAffine = affine() || geo.affine();
378 // make sure that for affine grids the geometry info is also correct
379 assert( affine() ? geo.affine() : true );
380
381 // in case of affine mappings we only have to multiply with a factor
382 if( isAffine && !caller.hasMass() )
383 {
384 const double massVolInv = getAffineMassFactor( geo );
385
386 // apply inverse mass matrix
387 for( int l = 0; l < dgNumDofs; ++l )
388 lf[ l ] *= massVolInv;
389 }
390 else
391 {
392 // copy local function to right hand side
393 for( int l = 0; l < dgNumDofs; ++l )
394 dgRhs_[ l ] = lf[ l ];
395
396 buildMatrix( caller, entity, geo, basisFunctionSet, dgNumDofs, dgMatrix_ );
397 dgMatrix_.solve( dgX_, dgRhs_ );
398
399 // copy back to local function
400 for( int l = 0; l < dgNumDofs; ++l )
401 lf[ l ] = dgX_[ l ];
402 }
403 }
404
406 template< class LocalMatrix >
407 void rightMultiplyInverseDgOrthoNormalBasis ( LocalMatrix &localMatrix ) const
408 {
409 const EntityType &entity = localMatrix.rangeEntity();
410 Geometry geo = entity.geometry();
411 assert( dgNumDofs == localMatrix.columns() );
412
413 // in case of affine mappings we only have to multiply with a factor
414 if( affine() || geo.affine() )
415 {
416 localMatrix.scale( getAffineMassFactor( geo ) );
417 }
418 else
419 {
420 NoMassDummyCaller caller;
421 buildMatrix( caller, entity, geo, localMatrix.rangeBasisFunctionSet(), dgNumDofs, dgMatrix_ );
422 dgMatrix_.invert();
423
424 const int rows = localMatrix.rows();
425 for( int i = 0; i < rows; ++i )
426 {
427 for( int j = 0; j < dgNumDofs; ++j )
428 dgRhs_[ j ] = localMatrix.get( i, j );
429 dgMatrix_.mtv( dgRhs_, dgX_ );
430 for( int j = 0; j < dgNumDofs; ++j )
431 localMatrix.set( i, j, dgX_[ j ] );
432 }
433 }
434 }
435
437 template< class LocalMatrix >
438 void leftMultiplyInverseDgOrthoNormalBasis ( LocalMatrix &localMatrix ) const
439 {
440 const EntityType &entity = localMatrix.domainEntity();
441 Geometry geo = entity.geometry();
442 assert( dgNumDofs == localMatrix.columns() );
443
444 // in case of affine mappings we only have to multiply with a factor
445 if( affine() || geo.affine() )
446 {
447 localMatrix.scale( getAffineMassFactor( geo ) );
448 }
449 else
450 {
451 NoMassDummyCaller caller;
452 buildMatrix( caller, entity, geo, localMatrix.domainBasisFunctionSet(), dgNumDofs, dgMatrix_ );
453 dgMatrix_.invert();
454
455 const int rows = localMatrix.rows();
456 for( int i = 0; i < rows; ++i )
457 {
458 for( int j = 0; j < dgNumDofs; ++j )
459 dgRhs_[ j ] = localMatrix.get( i, j );
460 dgMatrix_.mv( dgRhs_, dgX_ );
461 for( int j = 0; j < dgNumDofs; ++j )
462 localMatrix.set( i, j, dgX_[ j ] );
463 }
464 }
465 }
466
468 bool entityHasChanged( const EntityType& entity ) const
469 {
470 // don't compute matrix new for the same entity
471 const int currentSequence = space().sequence();
472 const unsigned int topologyId = entity.type().id();
473 const IndexType entityIndex = indexSet_.index( entity ) ;
474
475 // check whether sequence has been updated
476 if( sequence_ != currentSequence ||
477 lastEntityIndex_ != entityIndex ||
478 lastTopologyId_ != topologyId )
479 {
480 // update identifiers
481 lastEntityIndex_ = entityIndex ;
482 sequence_ = currentSequence;
483 lastTopologyId_ = topologyId ;
484
485 return true ;
486 }
487 else
488 // the entity did not change
489 return false ;
490 }
491
493 // standard applyInverse method
497 template< class MassCaller, class BasisFunctionSet, class LocalFunction >
498 void applyInverseDefault ( MassCaller &caller, const EntityType &entity,
499 const Geometry &geo, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf ) const
500 {
501 // get local inverted mass matrix
502 MatrixType &invMassMatrix
503 = getLocalInverseMassMatrixDefault ( caller, entity, geo, basisFunctionSet );
504
505 // copy local function to right hand side
506 const int numDofs = lf.size();
507 rhs_.resize( numDofs );
508 for( int l = 0; l < numDofs; ++l )
509 rhs_[ l ] = lf[ l ];
510
511 // apply inverse to right hand side and store in lf
512 multiply( numDofs, invMassMatrix, rhs_, lf );
513 }
514
516 template< class LocalMatrix >
517 void rightMultiplyInverseDefault ( const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix ) const
518 {
519 NoMassDummyCaller caller;
520 MatrixType &invMassMatrix
521 = getLocalInverseMassMatrixDefault ( caller, entity, geo, localMatrix.rangeBasisFunctionSet() );
522
523 const int cols = localMatrix.columns();
524 rhs_.resize( cols );
525 row_.resize( cols );
526
527 const int rows = localMatrix.rows();
528 for( int i = 0; i < rows; ++i )
529 {
530 // get i-th row from localMatrix
531 for( int j = 0; j < cols; ++j )
532 rhs_[ j ] = localMatrix.get( i, j );
533
534 // multiply with all columns of inverse mass matrix
535 invMassMatrix.mtv( rhs_, row_ );
536
537 // store as i-th row in localMatrix
538 for( int j = 0; j < cols; ++j )
539 localMatrix.set( i, j, row_[ j ] );
540 }
541 }
542
544 template< class LocalMatrix >
545 void leftMultiplyInverseDefault ( const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix ) const
546 {
547 NoMassDummyCaller caller;
548 MatrixType &invMassMatrix
549 = getLocalInverseMassMatrixDefault ( caller, entity, geo, localMatrix.rangeBasisFunctionSet() );
550
551 const int cols = localMatrix.columns();
552 rhs_.resize( cols );
553 row_.resize( cols );
554
555 const int rows = localMatrix.rows();
556 for( int i = 0; i < rows; ++i )
557 {
558 // get i-th column from localMatrix
559 for( int j = 0; j < cols; ++j )
560 rhs_[ j ] = localMatrix.get( j, i );
561
562 // multiply with all rows in inverse mass matrix
563 invMassMatrix.mv( rhs_, row_ );
564
565 // store as i-th column in localMatrix
566 for( int j = 0; j < cols; ++j )
567 localMatrix.set( j, i, row_[ j ] );
568 }
569 }
570
571
573 // local applyInverse method for affine geometries
576 template< class BasisFunctionSet, class LocalFunction >
577 void applyInverseLocally ( const EntityType &entity,
578 const Geometry &geo, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf ) const
579 {
580 const int numDofs = lf.size();
581
582 // get local inverted mass matrix
583 MatrixPairType& matrixPair =
584 getLocalInverseMassMatrix( entity, geo, basisFunctionSet, numDofs );
585
586 // if diagonal exists then matrix is in diagonal form
587 if( matrixPair.second )
588 {
589 const VectorType& diagonal = *matrixPair.second;
590 assert( int(diagonal.size()) == numDofs );
591
592 VolumeQuadratureType volQuad( entity, volumeQuadratureOrder( entity ) );
593
594 const int nop = volQuad.nop();
595 assert(nop*dimRange == numDofs);
596 for( int l=0, qt = 0; qt < nop; ++qt )
597 {
598 const auto intel = geo.integrationElement( volQuad.point(qt) );
599 for (int r = 0; r < dimRange; ++r, ++l )
600 {
601 lf[ l ] *= diagonal[ l ] / intel;
602 }
603 }
604 }
605 else
606 {
607 const double massVolInv = getAffineMassFactor( geo );
608 // copy local function to right hand side
609 // and apply inverse mass volume fraction
610 rhs_.resize( numDofs );
611 for( int l = 0; l < numDofs; ++l )
612 rhs_[ l ] = lf[ l ] * massVolInv;
613
614 const MatrixType& invMassMatrix = *matrixPair.first;
615 // apply inverse local mass matrix and store in lf
616 multiply( numDofs, invMassMatrix, rhs_, lf );
617 }
618 }
619
620 template <class LocalMatrix>
621 const VectorType&
622 setupInverseDiagonal( const EntityType &entity, const Geometry &geo,
623 const VectorType& refElemDiagonal,
624 LocalMatrix &localMatrix ) const
625 {
626 const int cols = localMatrix.columns();
627
628 assert( int(refElemDiagonal.size()) == cols );
629
630 VolumeQuadratureType volQuad( entity, volumeQuadratureOrder( entity ) );
631
632 VectorType& elementDiagonal = rhs_;
633 elementDiagonal.resize( cols );
634
635 const int nop = volQuad.nop();
636 assert(nop*dimRange == cols);
637 for( int l = 0, qt = 0; qt < nop; ++qt )
638 {
639 const auto intel = geo.integrationElement( volQuad.point(qt) );
640 for (int r = 0; r < dimRange; ++r,++l )
641 {
642 elementDiagonal[ l ] = refElemDiagonal[ l ] / intel;
643 }
644 }
645 return elementDiagonal;
646 }
647
648 template< class LocalMatrix >
649 void rightMultiplyInverseLocally ( const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix ) const
650 {
651 const int cols = localMatrix.columns();
652 MatrixPairType& matrixPair =
653 getLocalInverseMassMatrix( entity, geo, localMatrix.rangeBasisFunctionSet(), cols );
654
655 // if diagonal exists then matrix is in diagonal form
656 // stored as inverse on the reference element
657 if( matrixPair.second )
658 {
659 const VectorType& elementDiagonal =
660 setupInverseDiagonal( entity, geo, *matrixPair.second, localMatrix );
661
662 row_.resize( cols );
663 const int rows = localMatrix.rows();
664 for( int i = 0; i < rows; ++i )
665 {
666 // get i-th row from localMatrix
667 // and multiply with diagonal of inverse mass matrix
668 for( int j = 0; j < cols; ++j )
669 row_[ j ] = elementDiagonal[ j ] * localMatrix.get( i, j );
670
671 // store as i-th row in localMatrix
672 for( int j = 0; j < cols; ++j )
673 localMatrix.set( i, j, row_[ j ] );
674 }
675 }
676 else
677 {
678 const MatrixType &invMassMatrix = *matrixPair.first;
679
680 const double massVolInv = getAffineMassFactor( geo );
681
682 rhs_.resize( cols );
683 row_.resize( cols );
684
685 const int rows = localMatrix.rows();
686 for( int i = 0; i < rows; ++i )
687 {
688 // get i-th row from localMatrix
689 // and multiply with diagonal of inverse mass matrix
690 for( int j = 0; j < cols; ++j )
691 rhs_[ j ] = localMatrix.get( i, j ) * massVolInv;
692
693 // multiply with all columns of inverse mass matrix
694 invMassMatrix.mtv( rhs_, row_ );
695
696 // store as i-th row of localMatrix
697 for( int j = 0; j < cols; ++j )
698 localMatrix.set( i, j, row_[ j ] );
699 }
700 }
701 }
702
704 template< class LocalMatrix >
705 void leftMultiplyInverseLocally ( const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix ) const
706 {
707 const int cols = localMatrix.columns();
708 MatrixPairType& matrixPair =
709 getLocalInverseMassMatrix( entity, geo, localMatrix.rangeBasisFunctionSet(), cols );
710
711 // if diagonal exists then matrix is in diagonal form
712 // stored as inverse on the reference element
713 if( matrixPair.second )
714 {
715 const VectorType& elementDiagonal =
716 setupInverseDiagonal( entity, geo, *matrixPair.second, localMatrix );
717
718 row_.resize( cols );
719 const int rows = localMatrix.rows();
720 for( int i = 0; i < rows; ++i )
721 {
722 // get i-th column from localMatrix
723 // and multiply with diagonal of inverse mass matrix
724 for( int j = 0; j < cols; ++j )
725 row_[ j ] = elementDiagonal[ j ] * localMatrix.get( j, i );
726
727 // store as i-th column of localMatrix
728 for( int j = 0; j < cols; ++j )
729 localMatrix.set( j, i, row_[ j ] );
730 }
731 }
732 else
733 {
734 const MatrixType &invMassMatrix = *matrixPair.first;
735
736 const double massVolInv = getAffineMassFactor( geo );
737
738 rhs_.resize( cols );
739 row_.resize( cols );
740
741 const int rows = localMatrix.rows();
742 for( int i = 0; i < rows; ++i )
743 {
744 // get i-th column from localMatrix
745 for( int j = 0; j < cols; ++j )
746 rhs_[ j ] = localMatrix.get( j, i ) * massVolInv;
747
748 // apply to all rows of inverse mass matrix
749 invMassMatrix.mv( rhs_, row_ );
750
751 // store as i-th column of localMatrix
752 for( int j = 0; j < cols; ++j )
753 localMatrix.set( j, i, row_[ j ] );
754 }
755 }
756 }
757
758
760 bool setup () const
761 {
762 // for structured grids this is always true
763 if( StructuredGrid )
764 return true;
765
766 // get types for codim 0
767 const std::vector<Dune::GeometryType>& geomTypes = geoInfo_.geomTypes(0);
768
769 // for simplices we also have affine mappings
770 if( (geomTypes.size() == 1) && geomTypes[0].isSimplex() )
771 {
772 return true;
773 }
774
775 // otherwise use geometry affinity
776 return false ;
777 }
778
780 template< class MassCaller, class Matrix >
781 void buildMatrix ( MassCaller &caller, const EntityType &entity,
782 const Geometry &geo, const BasisFunctionSetType &set,
783 std::size_t numDofs, Matrix &matrix ) const
784 {
785 assert( numDofs == set.size() );
786
787 // clear matrix
788 matrix = 0;
789
790 // create quadrature
791 VolumeQuadratureType volQuad( entity, volumeQuadratureOrder( entity ) );
792
793 if( caller.hasMass() )
794 buildMatrixWithMassFactor( caller, entity, geo, set, volQuad, numDofs, matrix );
795 else
796 buildMatrixNoMassFactor( entity, geo, set, volQuad, numDofs, matrix );
797 }
798
800 template <class Matrix>
802 const EntityType& en,
803 const Geometry& geo,
804 const BasisFunctionSetType& set,
805 const VolumeQuadratureType& volQuad,
806 const int numDofs,
807 Matrix& matrix,
808 const bool applyIntegrationElement = true ) const
809 {
810 const int volNop = volQuad.nop();
811 for(int qp=0; qp<volNop; ++qp)
812 {
813 // calculate integration weight
814 const double intel = ( applyIntegrationElement ) ?
815 ( volQuad.weight(qp) * geo.integrationElement(volQuad.point(qp)) ) : volQuad.weight(qp) ;
816
817 // eval basis functions
818 set.evaluateAll(volQuad[qp], phi_);
819
820 for(int m=0; m<numDofs; ++m)
821 {
822 const RangeType& phi_m = phi_[m];
823 const ctype val = intel * (phi_m * phi_m);
824 matrix[m][m] += val;
825
826 for(int k=m+1; k<numDofs; ++k)
827 {
828 const ctype val = intel * (phi_m * phi_[k]);
829 matrix[m][k] += val;
830 matrix[k][m] += val;
831 }
832 }
833 }
834 }
835
837 template <class MassCallerType, class Matrix>
839 MassCallerType& caller,
840 const EntityType& en,
841 const Geometry& geo,
842 const BasisFunctionSetType& set,
843 const VolumeQuadratureType& volQuad,
844 const int numDofs,
845 Matrix& matrix) const
846 {
847 typedef typename MassCallerType :: MassFactorType MassFactorType;
848 MassFactorType mass;
849
850 const int volNop = volQuad.nop();
851 for(int qp=0; qp<volNop; ++qp)
852 {
853 // calculate integration weight
854 const double intel = volQuad.weight(qp)
855 * geo.integrationElement(volQuad.point(qp));
856
857 // eval basis functions
858 set.evaluateAll( volQuad[qp], phi_);
859
860 // call mass factor
861 caller.mass( en, volQuad, qp, mass);
862
863 // apply mass matrix to all basis functions
864 for(int m=0; m<numDofs; ++m)
865 {
866 mass.mv( phi_[m], phiMass_[m] );
867 }
868
869 // add values to matrix
870 for(int m=0; m<numDofs; ++m)
871 {
872 for(int k=0; k<numDofs; ++k)
873 {
874 matrix[m][k] += intel * (phiMass_[m] * phi_[k]);
875 }
876 }
877 }
878 }
879
880 // implement matvec with matrix (mv of densematrix is too stupid)
881 template <class Matrix, class Rhs, class X>
882 void multiply( const int size,
883 const Matrix& matrix,
884 const Rhs& rhs,
885 X& x ) const
886 {
887 assert( (int) matrix.rows() == size );
888 assert( (int) matrix.cols() == size );
889 assert( (int) rhs.size() == size );
890
891 for( int row = 0; row < size; ++ row )
892 {
893 RangeFieldType sum = 0;
894 // get matrix row
895 typedef typename Matrix :: const_row_reference MatRow;
896 MatRow matRow = matrix[ row ];
897
898 // multiply row with right hand side
899 for( int col = 0; col < size; ++ col )
900 {
901 sum += matRow[ col ] * rhs[ col ];
902 }
903
904 // set to result to result vector
905 x[ row ] = sum;
906 }
907 }
908 };
909
910
911
912 // LocalMassMatrix
913 // ---------------
914
916 template< class DiscreteFunctionSpace, class VolumeQuadrature >
918 : public LocalMassMatrixImplementation< DiscreteFunctionSpace, VolumeQuadrature >
919 {
921
922 public:
923 // copy base class constructors
924 using BaseType :: BaseType;
925 };
926
927
928
930 //
931 // DG LocalMassMatrix Implementation
932 //
934
936 template< class DiscreteFunctionSpace, class VolumeQuadrature, bool refElemScaling = true >
938 : public LocalMassMatrixImplementation< DiscreteFunctionSpace, VolumeQuadrature, refElemScaling >
939 {
941
942 public:
943 typedef typename BaseType :: EntityType EntityType;
944
945 // copy base class constructors
947
950 template <class MassCallerType, class BasisFunction, class LocalFunctionType>
951 void applyInverse(MassCallerType& caller,
952 const EntityType& en,
953 const BasisFunction &basisFunction,
954 LocalFunctionType& lf) const
955 {
956 BaseType :: applyInverseDgOrthoNormalBasis( caller, en, basisFunction, lf );
957 }
958 template <class MassCallerType, class LocalFunctionType>
959 void applyInverse(MassCallerType& caller,
960 const EntityType& en,
961 LocalFunctionType& lf) const
962 {
963 BaseType :: applyInverseDgOrthoNormalBasis( caller, en, lf.basisFunctionSet(), lf );
964 }
965
967 template <class LocalFunctionType>
968 void applyInverse(const EntityType& en,
969 LocalFunctionType& lf) const
970 {
971 typename BaseType :: NoMassDummyCaller caller;
972 applyInverse(caller, en, lf );
973 }
974
975 template <class BasisFunction, class LocalFunctionType>
976 void applyInverse(const EntityType& en,
977 const BasisFunction &basisFunction,
978 LocalFunctionType& lf) const
979 {
980 typename BaseType :: NoMassDummyCaller caller;
981 applyInverse(caller, en, basisFunction, lf );
982 }
983
985 template< class LocalFunction >
986 void applyInverse ( LocalFunction &lf ) const
987 {
988 applyInverse( lf.entity(), lf.basisFunctionSet(), lf );
989 }
990
992 template< class LocalMatrix >
993 void rightMultiplyInverse ( LocalMatrix &localMatrix ) const
994 {
996 }
997
999 template< class LocalMatrix >
1000 void leftMultiplyInverse ( LocalMatrix &localMatrix ) const
1001 {
1003 }
1004 };
1005
1007
1008 } // namespace Fem
1009
1010} // namespace Dune
1011
1012#endif // #ifndef DUNE_FEM_LOCALMASSMATRIX_HH
discrete function space
void solve(V1 &x, const V2 &b, bool doPivoting=true) const
Solve system A x = b.
void mv(const X &x, Y &y) const
y = A x
Definition: densematrix.hh:368
void invert(bool doPivoting=true)
Compute inverse.
void mtv(const X &x, Y &y) const
y = A^T x
Definition: densematrix.hh:387
constexpr size_type rows() const
number of rows
Definition: densematrix.hh:709
void resize(size_type r, size_type c, value_type v=value_type())
resize matrix to r × c
Definition: dynmatrix.hh:106
Error thrown if operations of a FieldMatrix fail.
Definition: densematrix.hh:126
BaseType::IndexType IndexType
index type *‍/
Definition: adaptiveleafindexset.hh:125
const std ::vector< GeometryType > & geomTypes(unsigned int codim) const
returns vector with geometry tpyes this index set has indices for
Definition: allgeomtypes.hh:171
Interface class for basis function sets.
Definition: basisfunctionset.hh:32
const EntityType & entity() const
return entity
std::size_t size() const
return size of basis function set
ctype referenceVolume(const GeometryType &type) const
return volume of reference element for geometry of type type
Definition: allgeomtypes.hh:72
FieldVector< ctype, dim > DomainType
type of domain vector
Definition: allgeomtypes.hh:51
interface for local functions
Definition: localfunction.hh:77
const EntityType & entity() const
obtain the entity, this local function lives on
Definition: localfunction.hh:302
const BasisFunctionSetType & basisFunctionSet() const
obtain the basis function set for this local function
Definition: localfunction.hh:296
SizeType size() const
obtain the number of local DoFs
Definition: localfunction.hh:360
DG Local Mass Matrix for arbitrary spaces.
Definition: localmassmatrix.hh:939
void applyInverse(const EntityType &en, LocalFunctionType &lf) const
apply local dg mass matrix to local function lf without mass factor
Definition: localmassmatrix.hh:968
void rightMultiplyInverse(LocalMatrix &localMatrix) const
compute localMatrix * M^-1
Definition: localmassmatrix.hh:993
void applyInverse(MassCallerType &caller, const EntityType &en, const BasisFunction &basisFunction, LocalFunctionType &lf) const
Definition: localmassmatrix.hh:951
void applyInverse(LocalFunction &lf) const
apply local dg mass matrix to local function lf without mass factor
Definition: localmassmatrix.hh:986
void leftMultiplyInverse(LocalMatrix &localMatrix) const
compute M^-1 * localMatrix
Definition: localmassmatrix.hh:1000
Local Mass Matrix inversion implementation, select the correct method in your implementation.
Definition: localmassmatrix.hh:34
void buildMatrixNoMassFactor(const EntityType &en, const Geometry &geo, const BasisFunctionSetType &set, const VolumeQuadratureType &volQuad, const int numDofs, Matrix &matrix, const bool applyIntegrationElement=true) const
build local mass matrix with mass factor
Definition: localmassmatrix.hh:801
void applyInverseDefault(MassCaller &caller, const EntityType &entity, const Geometry &geo, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf) const
Definition: localmassmatrix.hh:498
void leftMultiplyInverse(LocalMatrix &localMatrix) const
compute M^-1 * localMatrix
Definition: localmassmatrix.hh:349
void leftMultiplyInverseLocally(const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix) const
compute M^-1 * localMatrix
Definition: localmassmatrix.hh:705
bool entityHasChanged(const EntityType &entity) const
returns true if the entity has been changed
Definition: localmassmatrix.hh:468
LocalMassMatrixImplementation(const DiscreteFunctionSpaceType &spc, int volQuadOrd)
constructor taking space and volume quadrature order
Definition: localmassmatrix.hh:217
void applyInverse(MassCaller &caller, const EntityType &entity, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf) const
Definition: localmassmatrix.hh:295
bool affine() const
returns true if geometry mapping is affine
Definition: localmassmatrix.hh:256
double getAffineMassFactor(const Geometry &geo) const
return mass factor for diagonal mass matrix
Definition: localmassmatrix.hh:259
void applyInverseLocally(const EntityType &entity, const Geometry &geo, const BasisFunctionSet &basisFunctionSet, LocalFunction &lf) const
apply local mass matrix to local function lf
Definition: localmassmatrix.hh:577
void applyInverse(const EntityType &entity, LocalFunction &lf) const
apply local dg mass matrix to local function lf without mass factor
Definition: localmassmatrix.hh:315
void applyInverse(LocalFunction &lf) const
apply local dg mass matrix to local function lf without mass factor
Definition: localmassmatrix.hh:330
void buildMatrix(MassCaller &caller, const EntityType &entity, const Geometry &geo, const BasisFunctionSetType &set, std::size_t numDofs, Matrix &matrix) const
build local mass matrix
Definition: localmassmatrix.hh:781
void rightMultiplyInverseDgOrthoNormalBasis(LocalMatrix &localMatrix) const
compute localMatrix * M^-1
Definition: localmassmatrix.hh:407
int maxVolumeQuadratureOrder() const
return appropriate quadrature order, default is 2 * order()
Definition: localmassmatrix.hh:204
LocalMassMatrixImplementation(const ThisType &other)
copy constructor
Definition: localmassmatrix.hh:239
int volumeQuadratureOrder(const EntityType &entity) const
return appropriate quadrature order, default is 2 * order(entity)
Definition: localmassmatrix.hh:211
void rightMultiplyInverseDefault(const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix) const
compute localMatrix * M^-1
Definition: localmassmatrix.hh:517
void applyInverse(MassCaller &caller, const EntityType &entity, LocalFunction &lf) const
Definition: localmassmatrix.hh:308
void buildMatrixWithMassFactor(MassCallerType &caller, const EntityType &en, const Geometry &geo, const BasisFunctionSetType &set, const VolumeQuadratureType &volQuad, const int numDofs, Matrix &matrix) const
build local mass matrix with mass factor
Definition: localmassmatrix.hh:838
void rightMultiplyInverse(LocalMatrix &localMatrix) const
compute localMatrix * M^-1
Definition: localmassmatrix.hh:337
void leftMultiplyInverseDefault(const EntityType &entity, const Geometry &geo, LocalMatrix &localMatrix) const
compute M^-1 * localMatrix
Definition: localmassmatrix.hh:545
LocalMassMatrixImplementation(const DiscreteFunctionSpaceType &spc, std::function< int(const int)> volQuadOrderFct=[](const int order) { return Capabilities::DefaultQuadrature< DiscreteFunctionSpaceType >::volumeOrder(order);})
constructor taking space and volume quadrature order
Definition: localmassmatrix.hh:222
bool setup() const
setup and return affinity
Definition: localmassmatrix.hh:760
void leftMultiplyInverseDgOrthoNormalBasis(LocalMatrix &localMatrix) const
compute M^-1 * localMatrix
Definition: localmassmatrix.hh:438
Local Mass Matrix for arbitrary spaces.
Definition: localmassmatrix.hh:919
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:114
Wrapper class for geometries.
Definition: geometry.hh:71
Volume integrationElement(const LocalCoordinate &local) const
Return the factor appearing in the integral transformation formula.
Definition: geometry.hh:265
bool affine() const
Return true if the geometry mapping is affine and false otherwise.
Definition: geometry.hh:197
Compute indices for geometry types, taking the dimension into account.
Definition: typeindex.hh:90
static constexpr std::size_t index(const GeometryType &gt)
Compute the index for the given geometry type over all dimensions.
Definition: typeindex.hh:138
static constexpr std::size_t size(std::size_t maxdim)
Compute total number of geometry types up to and including the given dimension.
Definition: typeindex.hh:125
A generic dynamic dense matrix.
Definition: matrix.hh:561
This file implements a dense matrix with dynamic numbers of rows and columns.
Implements a matrix constructed from a given type representing a field and compile-time given number ...
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Specialize with 'true' if the grid is a Cartesian grid. Cartesian grids satisfy the following propert...
Definition: capabilities.hh:48
static int volumeOrder(const int k)
return quadrature order for volume quadratures for given polynomial order k
Definition: capabilities.hh:138
Helper class to check affinity of the grid's geometries.
Definition: checkgeomaffinity.hh:22
selects Obj::pointSetId if available, otherwise defaultValue (default is -1)
Definition: utility.hh:174
Helper classes to provide indices for geometrytypes for use in a vector.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 24, 22:29, 2024)