1#ifndef DUNE_FEM_SCHEMES_MASSLUMPING_HH
2#define DUNE_FEM_SCHEMES_MASSLUMPING_HH
5#include <dune/fem/schemes/galerkin.hh>
6#include <dune/fem/function/localfunction/temporary.hh>
7#include <dune/fem/common/bindguard.hh>
8#include <dune/fem/quadrature/lumpingquadrature.hh>
18 template <
typename DomainFunction,
typename RangeFunction >
19 class PetscLinearOperator ;
25 template<
class Integrands,
class MassIntegrands,
class DomainFunction,
class RangeFunction = DomainFunction >
26 struct MassLumpingOperator
27 :
public virtual Operator< DomainFunction, RangeFunction >
29 typedef DomainFunction DomainFunctionType;
30 typedef RangeFunction RangeFunctionType;
33 static_assert( std::is_same< typename DomainFunctionType::GridPartType, typename RangeFunctionType::GridPartType >::value,
"DomainFunction and RangeFunction must be defined on the same grid part." );
35 typedef typename RangeFunctionType::GridPartType GridPartType;
38 typedef Impl::GalerkinOperator< GridPartType > GalerkinOperatorImplType;
39 typedef Impl::LocalGalerkinOperator< Integrands > LocalGalerkinOperatorImplType;
41 template <
class Space>
42 struct LumpingQuadratureSelector
44 typedef typename Space :: GridPartType GridPartType;
45 typedef CachingLumpingQuadrature< GridPartType, 0 > InteriorQuadratureType;
48 typedef CachingQuadrature< GridPartType, 1, Capabilities::DefaultQuadrature< Space > :: template DefaultQuadratureTraits > SurfaceQuadratureType;
52 typedef Impl::LocalGalerkinOperator< MassIntegrands, LumpingQuadratureSelector > MassOperatorImplType;
54 typedef typename RangeFunctionType :: DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
56 template<
class... Args >
57 explicit MassLumpingOperator (
const GridPartType &gridPart,
58 const Integrands& integrands,
59 const MassIntegrands& massIntegrands,
61 : iterators_( gridPart ),
63 localOp_( gridPart,
std::move( integrands ),
std::forward< Args >( args )... ),
64 mass_( gridPart,
std::move( massIntegrands ),
std::forward< Args >( args )... ),
65 gridSizeInterior_( 0 ),
68 if( mass().hasSkeleton() )
69 DUNE_THROW(InvalidStateException,
"MassLumpingOperator: Mass model cannot have a skeleton term");
72 auto interiorOrder = [] (
const int order) {
return order; };
74 auto surfaceOrder = [] (
const int order) {
return 0; };
77 size_t size = mass_.size();
78 for(
size_t i=0; i<
size; ++i )
79 mass_[ i ].setQuadratureOrderFunctions( interiorOrder, surfaceOrder );
82 void setCommunicate(
const bool communicate )
84 communicate_ = communicate;
87 std::cout <<
"MassLumpingOperator::setCommunicate: communicate was disabled!" << std::endl;
91 void setQuadratureOrders(
unsigned int interior,
unsigned int surface)
94 size_t size = localOp_.size();
95 for(
size_t i=0; i<
size; ++i )
96 localOp_[ i ].setQuadratureOrders(interior,surface);
99 virtual void operator() (
const DomainFunctionType &u, RangeFunctionType &w )
const final override
104 template<
class Gr
idFunction >
105 void operator() (
const GridFunction &u, RangeFunctionType &w )
const
110 const GridPartType &gridPart ()
const {
return op().gridPart(); }
112 typedef Integrands ModelType;
113 typedef Integrands DirichletModelType;
114 ModelType &model()
const {
return localOperator().model(); }
116 [[deprecated(
"Use localOperator instead!")]]
117 const LocalGalerkinOperatorImplType& impl()
const {
return localOperator(); }
120 const LocalGalerkinOperatorImplType& localOperator()
const {
return (*localOp_); }
121 const MassOperatorImplType& mass()
const {
return (*mass_); }
123 std::size_t gridSizeInterior ()
const {
return gridSizeInterior_; }
126 const GalerkinOperatorImplType& op()
const {
return (*opImpl_); }
128 template<
class Gr
idFunction >
129 void evaluate(
const GridFunction &u, RangeFunctionType &w )
const
134 std::shared_mutex mutex;
136 auto doEval = [
this, &u, &w, &mutex] ()
139 std::tuple<
const LocalGalerkinOperatorImplType&,
140 const MassOperatorImplType& > integrands( localOperator(), mass() );
144 this->op().evaluate( u, w, this->iterators_, integrands, mutex );
147 bool singleThreadModeError = false ;
151 MPIManager :: run ( doEval );
154 gridSizeInterior_ = Impl::accumulateGridSize( opImpl_ );
156 catch (
const SingleThreadModeError& e )
158 singleThreadModeError =
true;
162 if( singleThreadModeError )
168 std::tuple<
const LocalGalerkinOperatorImplType&,
169 const MassOperatorImplType& > integrands( localOperator(), mass() );
171 op().evaluate( u, w, iterators_, integrands );
174 gridSizeInterior_ = op().gridSizeInterior();
184 mutable ThreadIteratorType iterators_;
187 ThreadSafeValue< MassOperatorImplType > mass_;
189 mutable std::size_t gridSizeInterior_;
198 template<
class Integrands,
class MassIntegrands,
class JacobianOperator >
199 class MassLumpingDifferentiableOperator
200 :
public MassLumpingOperator< Integrands, MassIntegrands, typename JacobianOperator::DomainFunctionType, typename JacobianOperator::RangeFunctionType >,
201 public DifferentiableOperator< JacobianOperator >
203 typedef MassLumpingOperator< Integrands, MassIntegrands, typename JacobianOperator::DomainFunctionType, typename JacobianOperator::RangeFunctionType > BaseType;
206 typedef typename BaseType :: LocalGalerkinOperatorImplType LocalGalerkinOperatorImplType;
207 typedef typename BaseType :: MassOperatorImplType MassOperatorImplType;
209 typedef JacobianOperator JacobianOperatorType;
211 typedef typename BaseType::DomainFunctionType DomainFunctionType;
212 typedef typename BaseType::RangeFunctionType RangeFunctionType;
213 typedef typename DomainFunctionType::DiscreteFunctionSpaceType DomainDiscreteFunctionSpaceType;
214 typedef typename RangeFunctionType::DiscreteFunctionSpaceType RangeDiscreteFunctionSpaceType;
216 typedef DiagonalAndNeighborStencil< DomainDiscreteFunctionSpaceType, RangeDiscreteFunctionSpaceType > DiagonalAndNeighborStencilType;
217 typedef DiagonalStencil< DomainDiscreteFunctionSpaceType, RangeDiscreteFunctionSpaceType > DiagonalStencilType;
219 typedef typename BaseType::GridPartType GridPartType;
221 template<
class... Args >
222 explicit MassLumpingDifferentiableOperator (
const DomainDiscreteFunctionSpaceType &dSpace,
223 const RangeDiscreteFunctionSpaceType &rSpace,
225 : BaseType( rSpace.gridPart(),
std::forward< Args >( args )... ),
228 domainSpaceSequence_(dSpace.sequence()),
229 rangeSpaceSequence_(rSpace.sequence()),
230 stencilDAN_(), stencilD_()
233 stencilDAN_.reset(
new DiagonalAndNeighborStencilType( dSpace_, rSpace_ ) );
235 stencilD_.reset(
new DiagonalStencilType( dSpace_, rSpace_ ) );
238 virtual void jacobian (
const DomainFunctionType &u, JacobianOperatorType &jOp )
const final override
244 template<
class Gr
idFunction >
245 void jacobian (
const GridFunction &u, JacobianOperatorType &jOp )
const
250 const DomainDiscreteFunctionSpaceType& domainSpace()
const
254 const RangeDiscreteFunctionSpaceType& rangeSpace()
const
259 const RangeDiscreteFunctionSpaceType& space()
const
264 using BaseType::gridPart;
265 using BaseType::localOperator;
268 bool hasSkeleton()
const
270 std::tuple< const LocalGalerkinOperatorImplType&, const MassOperatorImplType& > integrands( localOperator(), mass() );
271 return op().hasSkeleton( integrands );
275 using BaseType::mass;
276 using BaseType::iterators_;
277 using BaseType::gridSizeInterior_;
279 void prepare( JacobianOperatorType& jOp )
const
281 if ( domainSpaceSequence_ != domainSpace().sequence()
282 || rangeSpaceSequence_ != rangeSpace().sequence() )
284 domainSpaceSequence_ = domainSpace().sequence();
285 rangeSpaceSequence_ = rangeSpace().sequence();
288 assert( stencilDAN_ );
289 stencilDAN_->update();
299 jOp.reserve( *stencilDAN_ );
301 jOp.reserve( *stencilD_ );
306 template <
class Gr
idFunction >
307 void assemble(
const GridFunction &u, JacobianOperatorType &jOp )
const
312 bool singleThreadModeError =
false;
313 std::shared_mutex mutex;
315 auto doAssemble = [
this, &u, &jOp, &mutex] ()
318 std::tuple< const LocalGalerkinOperatorImplType&, const MassOperatorImplType& > integrands( localOperator(), mass() );
319 this->op().assemble( u, jOp, this->iterators_, integrands, mutex );
324 MPIManager :: run ( doAssemble );
327 gridSizeInterior_ = Impl::accumulateGridSize( this->opImpl_ );
329 catch (
const SingleThreadModeError& e )
331 singleThreadModeError =
true;
334 if (singleThreadModeError)
339 std::tuple< const LocalGalerkinOperatorImplType&, const MassOperatorImplType& > integrands( localOperator(), mass() );
340 op().assemble( u, jOp, iterators_, integrands );
343 gridSizeInterior_ = op().gridSizeInterior();
351 const DomainDiscreteFunctionSpaceType &dSpace_;
352 const RangeDiscreteFunctionSpaceType &rSpace_;
353 mutable int domainSpaceSequence_, rangeSpaceSequence_;
355 mutable std::unique_ptr< DiagonalAndNeighborStencilType > stencilDAN_;
356 mutable std::unique_ptr< DiagonalStencilType > stencilD_;
364 template<
class Integrands,
class DomainFunction,
class RangeFunction >
365 class MassLumpingAutomaticDifferenceGalerkinOperator
366 :
public MassLumpingOperator< Integrands, DomainFunction, RangeFunction >,
367 public AutomaticDifferenceOperator< DomainFunction, RangeFunction >
369 typedef MassLumpingOperator< Integrands, DomainFunction, RangeFunction > BaseType;
373 typedef typename BaseType::GridPartType GridPartType;
375 template<
class... Args >
376 explicit MassLumpingAutomaticDifferenceGalerkinOperator (
const GridPartType &gridPart, Args &&... args )
377 : BaseType( gridPart,
std::forward< Args >( args )... ), AutomaticDifferenceOperatorType()
388 template<
class Integrands,
class MassIntegrands,
389 class LinearOperator,
bool addDirichletBC,
390 template <
class,
class,
class>
class DifferentiableGalerkinOperatorImpl >
391 struct MassLumpingSchemeTraits
393 template <
class O,
bool addDBC>
394 struct DirichletBlockSelector {
using type = void; };
396 struct DirichletBlockSelector<O,true> {
using type =
typename O::DirichletBlockVector; };
398 using DifferentiableOperatorType = std::conditional_t< addDirichletBC,
399 DirichletWrapperOperator< DifferentiableGalerkinOperatorImpl< Integrands, MassIntegrands, LinearOperator >>,
400 DifferentiableGalerkinOperatorImpl< Integrands, MassIntegrands, LinearOperator > >;
402 using DirichletBlockVector =
typename DirichletBlockSelector<
403 DirichletWrapperOperator<
404 DifferentiableGalerkinOperatorImpl< Integrands, MassIntegrands, LinearOperator >>,
405 addDirichletBC>::type;
407 typedef DifferentiableOperatorType type;
413 template<
class Integrands,
class MassIntegrands,
414 class LinearOperator,
class LinearInverseOperator,
bool addDirichletBC,
415 template <
class,
class,
class>
class DifferentiableGalerkinOperatorImpl = MassLumpingDifferentiableOperator >
416 struct MassLumpingSchemeImpl :
public FemScheme<
417 typename MassLumpingSchemeTraits< Integrands, MassIntegrands, LinearOperator,
418 addDirichletBC, DifferentiableGalerkinOperatorImpl
420 LinearInverseOperator >
422 typedef FemScheme<
typename MassLumpingSchemeTraits< Integrands, MassIntegrands, LinearOperator,
423 addDirichletBC, DifferentiableGalerkinOperatorImpl>::type,
424 LinearInverseOperator >
428 typedef typename BaseType :: DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
431 typedef MassIntegrands MassModelType;
433 MassLumpingSchemeImpl (
const DiscreteFunctionSpaceType &dfSpace,
434 const Integrands &integrands,
435 const MassIntegrands& massIntegrands,
436 const ParameterReader& parameter = Parameter::container() )
439 std::move(integrands),
440 std::move(massIntegrands) )
449 template<
class Integrands,
class MassIntegrands,
class LinearOperator,
class InverseOperator,
bool addDirichletBC >
450 using MassLumpingScheme = Impl::MassLumpingSchemeImpl< Integrands, MassIntegrands, LinearOperator, InverseOperator, addDirichletBC,
451 MassLumpingDifferentiableOperator >;
static bool verbose()
obtain the cached value for fem.verbose with default verbosity level 2
Definition: parameter.hh:466
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
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