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:97
 
actual interface class for quadratures
 
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