1#ifndef DUNE_FEM_EVALUATECALLER_HH
2#define DUNE_FEM_EVALUATECALLER_HH
12#include <dune/fem/space/basisfunctionset/evaluatecallerdeclaration.hh>
14#include <dune/fem/misc/threads/threadsafevalue.hh>
15#include <dune/fem/common/utility.hh>
16#include <dune/fem/quadrature/quadrature.hh>
25#ifdef DUNE_FEM_INCLUDE_AUTOGENERATEDCODE_FILENAME_SPEC
26#define CODEGEN_INCLUDEMAXNUMS
28#include DUNE_FEM_INCLUDE_AUTOGENERATEDCODE_FILENAME_SPEC
29#undef CODEGEN_INCLUDEMAXNUMS
37#ifndef MAX_NUMBER_OF_QUAD_POINTS
38#define MAX_NUMBER_OF_QUAD_POINTS 20
41#ifndef MAX_NUMBER_OF_BASE_FCT
42#define MAX_NUMBER_OF_BASE_FCT 20
45#ifndef MIN_NUMBER_OF_QUAD_POINTS
46#define MIN_NUMBER_OF_QUAD_POINTS 1
49#ifndef MIN_NUMBER_OF_BASE_FCT
50#define MIN_NUMBER_OF_BASE_FCT 1
53#include <dune/fem/space/basisfunctionset/evaluatecallerdefaultimpl.hh>
55#ifdef DUNE_FEM_INCLUDE_AUTOGENERATEDCODE_FILENAME_SPEC
57#include DUNE_FEM_INCLUDE_AUTOGENERATEDCODE_FILENAME_SPEC
68 template <
class Traits,
73 template<
class QuadratureImp,
75 class LocalDofVectorImp,
76 class GeometryImp = EmptyGeometry >
77 struct EvaluateCallerInterfaceTraits
79 typedef QuadratureImp QuadratureType;
80 typedef FactorImp FactorType;
81 typedef LocalDofVectorImp LocalDofVectorType;
82 typedef GeometryImp Geometry;
85 template <
class Traits,
86 class BaseFunctionSet,
88 struct EvaluateCallerTraits
90 typedef Traits BaseTraits;
91 typedef typename Traits :: QuadratureType QuadratureType ;
92 typedef typename Traits :: FactorType FactorType ;
93 typedef typename Traits :: LocalDofVectorType LocalDofVectorType ;
94 typedef typename Traits :: Geometry Geometry ;
96 typedef BaseFunctionSet BaseFunctionSetType;
97 typedef RangeVectorImp RangeVectorType;
102 template <
class Traits>
103 class EvaluateCallerInterface
105 typedef EvaluateCallerInterface< Traits > ThisType;
107 typedef std::unique_ptr< ThisType > StoragePointerType;
110 static const int maxNumBaseFunctions = MAX_NUMBER_OF_BASE_FCT;
111 static const int minNumBaseFunctions = MIN_NUMBER_OF_BASE_FCT;
113 static const int maxQuadNop = MAX_NUMBER_OF_QUAD_POINTS;
114 static const int minQuadNop = MIN_NUMBER_OF_QUAD_POINTS;
117 static const int maxQuadratures = 25;
119 class EvaluatorStorage
121 class Item :
public std::pair< bool, StoragePointerType >
123 typedef std::pair< bool, StoragePointerType > BaseType;
126 Item() : BaseType(false, StoragePointerType() ) {}
130 std::vector< Item > storage_;
133 storage_( maxQuadratures ) {}
135 Item&
get(
const size_t id )
137 if(
id >= storage_.size() )
139 storage_.resize(
id + 10 );
141 return storage_[ id ];
146 EvaluateCallerInterface() {}
149 typedef typename Traits :: QuadratureType QuadratureType ;
150 typedef typename Traits :: FactorType FactorType ;
151 typedef typename Traits :: LocalDofVectorType LocalDofVectorType ;
152 typedef typename Traits :: Geometry Geometry ;
154 virtual ~EvaluateCallerInterface() {}
156 virtual void* storageAddress ()
const = 0;
157 virtual size_t storageSize ()
const = 0;
159 virtual void axpyRanges(
const QuadratureType&,
161 LocalDofVectorType & )
const = 0;
163 virtual void evaluateRanges(
const QuadratureType& quad,
164 const LocalDofVectorType & dofs,
165 FactorType& factors)
const = 0;
167 virtual void axpyJacobians(
const QuadratureType&,
170 LocalDofVectorType & )
const = 0;
172 virtual void evaluateJacobians(
const QuadratureType&,
174 const LocalDofVectorType&,
175 FactorType&)
const = 0;
177 template <
class BaseFunctionSet,
class Storage >
178 static const StoragePointerType& storage(
const BaseFunctionSet& baseSet,
179 const Storage& dataCache,
180 const QuadratureType& quad)
183 static ThreadSafeValue< EvaluatorStorage > evaluatorStorage;
184 EvaluatorStorage& evaluators = *evaluatorStorage;
187 const size_t quadId = quad.id();
188 auto& item = evaluators.get( quadId );
191 const int nop = quad.nop();
192 static const int dimRange = BaseFunctionSet :: FunctionSpaceType:: dimRange;
193 const int numBaseFct = baseSet.size() / dimRange;
195 typedef EvaluateCallerTraits< Traits, BaseFunctionSet, Storage> NewTraits;
198 if( quad.isInterpolationQuadrature( numBaseFct ) )
199 std::cout <<
"EvaluateCallerInterface::storage: Not creating implementation because of interpolation feature!" <<std::endl;
207 if( (nop >= minQuadNop && nop <= maxQuadNop) &&
208 (numBaseFct >= minNumBaseFunctions && numBaseFct <= maxNumBaseFunctions) &&
209 ! quad.isInterpolationQuadrature( numBaseFct ) )
212 EvaluateCaller< NewTraits, maxQuadNop, maxNumBaseFunctions >
213 :: create( dataCache , nop, numBaseFct ) );
225 template <
class Traits,
229 class EvaluateRealImplementation
230 :
public EvaluateCallerInterface< typename Traits :: BaseTraits >
233 typedef typename Traits :: BaseFunctionSetType BaseFunctionSetType;
234 typedef typename Traits :: QuadratureType QuadratureType ;
235 typedef typename Traits :: FactorType FactorType ;
236 typedef typename Traits :: LocalDofVectorType LocalDofVectorType ;
237 typedef typename Traits :: Geometry Geometry ;
238 typedef typename Traits :: RangeVectorType RangeVectorType ;
239 typedef typename RangeVectorType :: value_type :: field_type FieldType;
241 typedef EvaluateRealImplementation< Traits, dimRange, quadNop, numBaseFct > ThisType;
242 typedef EvaluateCallerInterface< typename Traits :: BaseTraits > BaseType;
246 RangeVectorType rangeStorage_;
248 std::vector< std::vector< FieldType > > rangeStorageTransposed_;
249 std::vector< std::vector< FieldType > > rangeStorageFlat_;
250 mutable std::vector< std::vector< std::vector< FieldType > > > rangeStorageTwisted_;
253 int getDim(
const DenseVector< K >& vec)
const
259 int getDim(
const DenseMatrix< K >& mat)
const
262 return getDim( mat[ 0 ] );
266 void initRangeStorageTransposed(
const std::integral_constant< bool, true > )
268 assert( rangeStorage_[ 0 ].
size() == 1 );
270 const int quadPoints = rangeStorage_.size() / numBaseFct;
271 const int faces = quadPoints / quadNop;
272 rangeStorageTransposed_.resize( faces );
273 for(
int f=0; f<faces; ++f )
275 auto& rangeStorageTransposed = rangeStorageTransposed_[ f ];
279 rangeStorageTransposed.resize( numBaseFct * quadNop );
280 for(
int i=0; i<numBaseFct; ++i )
282 const int idx = i * quadNop;
283 for(
int j=0; j<quadNop; ++j )
285 int qp = f * quadNop + j ;
286 assert( j*numBaseFct + i <
int(rangeStorage_.size()) );
288 rangeStorageTransposed[ idx + j ] = rangeStorage_[ qp*numBaseFct + i ][ 0 ];
296 void initRangeStorageTransposed(
const std::integral_constant< bool, false > )
298 const int dim = rangeStorage_[ 0 ][ 0 ].size();
300 const int quadPoints = rangeStorage_.size() / numBaseFct;
301 const int faces = quadPoints / quadNop;
302 rangeStorageTransposed_.resize( faces );
303 rangeStorageFlat_.resize( faces );
304 for(
int f=0; f<faces; ++f )
306 auto& rangeStorageTransposed = rangeStorageTransposed_[ f ];
307 auto& rangeStorageFlat = rangeStorageFlat_[ f ];
311 rangeStorageTransposed.resize( numBaseFct * quadNop * dim );
312 rangeStorageFlat.resize( numBaseFct * quadNop * dim );
313 for(
int i=0; i<numBaseFct; ++i )
315 const int idx = i * (quadNop * dim);
316 for(
int j=0; j<quadNop; ++j )
318 int qp = f * quadNop + j ;
319 for(
int d=0; d<dim; ++d )
321 rangeStorageFlat[ j*numBaseFct*dim + (i * dim) + d ] = rangeStorage_[ qp*numBaseFct + i ][ 0 ][ d ];
322 rangeStorageTransposed[ idx + (j * dim) + d ] = rangeStorage_[ qp*numBaseFct + i ][ 0 ][ d ];
330 template <
class Quadrature>
332 const std::vector< FieldType >&
333 getTwistedStorage(
const Quadrature& quad )
const
337 assert( ! rangeStorageTransposed_.empty() );
341 if constexpr ( Quadrature::twisted() )
343 if( quad.twistId() == 4 )
344 return rangeStorageTransposed_[ quad.localFaceIndex() ];
346 auto& rangeStorageTwisted = rangeStorageTwisted_[ quad.twistId() ];
347 if( rangeStorageTwisted.empty() )
349 const int quadPoints = rangeStorage_.size() / numBaseFct;
350 const int faces = quadPoints / quadNop;
351 rangeStorageTwisted.resize( faces );
354 const int f = quad.localFaceIndex() ;
355 auto& rangeStorageFace = rangeStorageTwisted[ f ];
356 if( rangeStorageFace.empty() )
359 const int dim = getDim( rangeStorage_[ 0 ] );
361 const auto& rangeStorageTransposed = rangeStorageTransposed_[ f ];
365 rangeStorageFace.resize( rangeStorageTransposed.size() );
366 for(
int i=0; i<numBaseFct; ++i )
368 const int idx = i * (quadNop * dim);
369 for(
int j=0; j<quadNop; ++j )
371 const int qp = quad.localCachingPoint( j );
372 for(
int d=0; d<dim; ++d )
374 rangeStorageFace[ idx + (j * dim) + d ] = rangeStorageTransposed[ idx + (qp * dim) + d ];
379 return rangeStorageFace;
383 return rangeStorageTransposed_[ quad.localFaceIndex() ];
390 EvaluateRealImplementation(
const RangeVectorType& rangeStorage )
391 : rangeStorage_( rangeStorage ), rangeStorageTwisted_( 8 )
393 initRangeStorageTransposed( std::integral_constant<
bool,
394 std::is_same<
typename RangeVectorType::value_type,
398 virtual void* storageAddress()
const {
return (
void *) &rangeStorage_ ; }
399 virtual size_t storageSize()
const {
return rangeStorage_.size() ; }
401 virtual void axpyRanges(
const QuadratureType& quad,
402 const FactorType& rangeFactors,
403 LocalDofVectorType & dofs )
const
405 Codegen::AxpyRanges< BaseFunctionSetType, Geometry, dimRange, quadNop, numBaseFct > :: axpy
406 ( quad, rangeStorage_, rangeFactors, dofs );
409 virtual void evaluateRanges(
const QuadratureType& quad,
410 const LocalDofVectorType & dofs,
411 FactorType& rangeFactors)
const
413 Codegen::EvaluateRanges< BaseFunctionSetType, Geometry, dimRange, quadNop, numBaseFct >
414 :: eval ( quad, getTwistedStorage( quad ), dofs, rangeFactors );
417 virtual void axpyJacobians(
const QuadratureType& quad,
418 const Geometry& geometry,
419 const FactorType& jacFactors,
420 LocalDofVectorType& dofs)
const
422 Codegen::AxpyJacobians< BaseFunctionSetType, Geometry, dimRange, quadNop, numBaseFct > :: axpy
423 ( quad, geometry, rangeStorageFlat_[ quad.localFaceIndex() ], jacFactors, dofs );
426 virtual void evaluateJacobians(
const QuadratureType& quad,
427 const Geometry& geometry,
428 const LocalDofVectorType& dofs,
429 FactorType& jacFactors)
const
431 Codegen::EvaluateJacobians< BaseFunctionSetType, Geometry, dimRange, quadNop, numBaseFct > :: eval
432 ( quad, geometry, getTwistedStorage( quad ), dofs, jacFactors );
435 static InterfaceType* create(
const RangeVectorType& rangeStorage )
437 return new ThisType( rangeStorage );
443 template <
class Traits,
447 class EvaluateImplementation
448 :
public EvaluateCallerInterface< typename Traits :: BaseTraits >
451 typedef typename Traits :: BaseFunctionSetType BaseFunctionSetType;
452 typedef typename Traits :: QuadratureType QuadratureType ;
453 typedef typename Traits :: FactorType FactorType ;
454 typedef typename Traits :: LocalDofVectorType LocalDofVectorType ;
455 typedef typename Traits :: Geometry Geometry ;
456 typedef typename Traits :: RangeVectorType RangeVectorType ;
458 typedef EvaluateImplementation< Traits, dimRange, quadNop, numBaseFct > ThisType;
460 typedef EvaluateCallerInterface< typename Traits :: BaseTraits > BaseType;
465 EvaluateImplementation(
const RangeVectorType& rangeStorage )
468 virtual void axpyRanges(
const QuadratureType& quad,
469 const FactorType& rangeFactors,
470 LocalDofVectorType & dofs )
const
472 std::cerr <<
"ERROR: EvaluateImplementation::axpyRanges not overloaded!" << std::endl;
476 virtual void axpyJacobians(
const QuadratureType& quad,
477 const Geometry& geometry,
478 const FactorType& jacFactors,
479 LocalDofVectorType& dofs)
const
481 std::cerr <<
"ERROR: EvaluateImplementation::axpyJacobians not overloaded!" << std::endl;
485 virtual void evaluateRanges(
const QuadratureType& quad,
486 const LocalDofVectorType & dofs,
487 FactorType& rangeFactors)
const
489 std::cerr <<
"ERROR: EvaluateImplementation::evaluateRanges not overloaded!" << std::endl;
493 virtual void evaluateJacobians(
const QuadratureType& quad,
494 const Geometry& geometry,
495 const LocalDofVectorType& dofs,
496 FactorType& jacFactors)
const
498 std::cerr <<
"ERROR: EvaluateImplementation::evaluateJacobians not overloaded!" << std::endl;
505 std::cout <<
"Optimized EvaluateImplementation for < dimR="<<dimRange<<
", qp=" << quadNop <<
", bases=" << numBaseFct <<
" > not created, falling back to default!" << std::endl;
513 template <
class Traits,
519 typedef typename Traits :: BaseFunctionSetType BaseFunctionSetType;
520 static const int dimRange = BaseFunctionSetType :: FunctionSpaceType:: dimRange;
521 typedef typename Traits :: RangeVectorType RangeVectorType ;
522 typedef EvaluateCallerInterface< typename Traits :: BaseTraits >
InterfaceType;
524 static InterfaceType* createObj(
const RangeVectorType& rangeStorage,
525 const size_t numbase )
527 if( numBaseFct == numbase )
528 return EvaluateImplementation< Traits, dimRange, quadNop, numBaseFct > :: create( rangeStorage );
530 return EvaluateCaller< Traits, quadNop, numBaseFct - 1 > :: createObj( rangeStorage, numbase );
533 static InterfaceType* create(
const RangeVectorType& rangeStorage,
534 const size_t quadnop,
const size_t numbase )
536 if( quadNop == quadnop )
537 return EvaluateCaller< Traits, quadNop, numBaseFct > :: createObj( rangeStorage, numbase );
539 return EvaluateCaller< Traits, quadNop - 1, numBaseFct > :: create( rangeStorage, quadnop, numbase );
543 template <
class Traits,
545 class EvaluateCaller< Traits, MIN_NUMBER_OF_QUAD_POINTS, numBaseFct >
548 typedef typename Traits :: BaseFunctionSetType BaseFunctionSetType;
549 static const int dimRange = BaseFunctionSetType :: FunctionSpaceType:: dimRange;
550 enum { quadNop = MIN_NUMBER_OF_QUAD_POINTS };
551 typedef typename Traits :: RangeVectorType RangeVectorType ;
552 typedef EvaluateCallerInterface< typename Traits :: BaseTraits >
InterfaceType;
554 static InterfaceType* createObj(
const RangeVectorType& rangeStorage,
555 const size_t numbase )
557 if( numBaseFct == numbase )
558 return EvaluateImplementation< Traits, dimRange, quadNop, numBaseFct > :: create( rangeStorage );
560 return EvaluateCaller< Traits, quadNop, numBaseFct - 1 > :: createObj( rangeStorage, numbase );
563 static InterfaceType* create(
const RangeVectorType& rangeStorage,
564 const size_t quadnop,
const size_t numbase )
566 if( quadNop == quadnop )
567 return EvaluateCaller< Traits, quadNop, numBaseFct > :: createObj( rangeStorage, numbase );
570 std::cerr <<
"ERROR: EvaluateCaller< "<< quadNop <<
", " << numBaseFct <<
" >::createObj: no working combination!" << std::endl;
576 template <
class Traits,
578 class EvaluateCaller< Traits, quadNop, MIN_NUMBER_OF_BASE_FCT >
581 typedef typename Traits :: BaseFunctionSetType BaseFunctionSetType;
582 static const int dimRange = BaseFunctionSetType :: FunctionSpaceType:: dimRange;
583 enum { numBaseFct = MIN_NUMBER_OF_BASE_FCT };
584 typedef typename Traits :: RangeVectorType RangeVectorType ;
585 typedef EvaluateCallerInterface< typename Traits :: BaseTraits >
InterfaceType;
587 static InterfaceType* createObj(
const RangeVectorType& rangeStorage,
588 const size_t numbase )
590 if( numBaseFct == numbase )
591 return EvaluateImplementation< Traits, dimRange, quadNop, numBaseFct > :: create( rangeStorage );
594 std::cerr <<
"ERROR: EvaluateCaller< "<< quadNop <<
", " << numBaseFct <<
" >::createObj: no working combination!" << std::endl;
599 static InterfaceType* create(
const RangeVectorType& rangeStorage,
600 const size_t quadnop,
const size_t numbase )
602 if( quadNop == quadnop )
603 return EvaluateCaller< Traits, quadNop, numBaseFct > :: createObj( rangeStorage, numbase );
606 return EvaluateCaller< Traits, quadNop - 1, numBaseFct > :: create( rangeStorage, quadnop, numbase );
611 template <
class Traits>
612 class EvaluateCaller< Traits, MIN_NUMBER_OF_QUAD_POINTS, MIN_NUMBER_OF_BASE_FCT>
615 typedef typename Traits :: BaseFunctionSetType BaseFunctionSetType;
616 static const int dimRange = BaseFunctionSetType :: FunctionSpaceType:: dimRange;
617 enum { quadNop = MIN_NUMBER_OF_QUAD_POINTS };
618 enum { numBaseFct = MIN_NUMBER_OF_BASE_FCT };
619 typedef typename Traits :: RangeVectorType RangeVectorType ;
620 typedef EvaluateCallerInterface< typename Traits :: BaseTraits >
InterfaceType;
622 static InterfaceType* createObj(
const RangeVectorType& rangeStorage,
623 const size_t numbase )
625 if( numBaseFct == numbase )
626 return EvaluateImplementation< Traits, dimRange, quadNop, numBaseFct > :: create( rangeStorage );
629 std::cerr <<
"ERROR: EvaluateCaller< "<< quadNop <<
", " << numBaseFct <<
" >::createObj: no working combination!" << std::endl;
634 static InterfaceType* create(
const RangeVectorType& rangeStorage,
635 const size_t quadnop,
const size_t numbase )
637 if( quadNop == quadnop )
638 return EvaluateCaller< Traits, quadNop, numBaseFct > :: createObj( rangeStorage, numbase );
641 std::cerr <<
"ERROR: EvaluateCaller< "<< quadNop <<
", " << numBaseFct <<
" >::create: no working combination!" << std::endl;
653#ifdef DUNE_FEM_INCLUDE_AUTOGENERATEDCODE_FILENAME_SPEC
654#define CODEGEN_INCLUDEEVALCALLERS
656#include DUNE_FEM_INCLUDE_AUTOGENERATEDCODE_FILENAME_SPEC
657#undef CODEGEN_INCLUDEEVALCALLERS
vector space out of a tensor product of fields.
Definition: fvector.hh:91
A few common exception classes.
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
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22