1#ifndef DUNE_FEM_SPACE_BASISFUNCTIONSET_TUPLE_HH
2#define DUNE_FEM_SPACE_BASISFUNCTIONSET_TUPLE_HH
10#include <dune/fem/common/forloop.hh>
14#include <dune/fem/common/utility.hh>
16#include <dune/fem/space/basisfunctionset/basisfunctionset.hh>
17#include <dune/fem/space/combinedspace/subobjects.hh>
18#include <dune/fem/storage/subvector.hh>
34 struct TupleSpaceProduct {};
35 struct TupleSpaceSummation {};
37 template<
class CombineOp,
class ... BasisFunctionSets >
38 class TupleBasisFunctionSet
40 typedef TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... > ThisType;
43 template<
int >
struct ComputeOffset;
44 template<
int >
struct EvaluateAll;
45 template<
int >
struct JacobianAll;
46 template<
int >
struct HessianAll;
47 template<
int >
struct EvaluateAllRanges;
48 template<
int >
struct JacobianAllRanges;
49 template<
int >
struct HessianAllRanges;
50 template<
int >
struct Axpy;
57 static constexpr int size () {
return std::tuple_element< j, std::tuple< std::integral_constant< int, i > ... > >::type::value; }
60 static constexpr std::integer_sequence< int, size< j >() ... > sizes ( std::integer_sequence< int, j ... > )
62 return std::integer_sequence< int, size< j >() ... >();
66 static constexpr int offset ()
68 return mysum( sizes( std::make_integer_sequence< int, j >() ) );
73 static constexpr int mysum ( std::integer_sequence< int, j ... > )
75 return Std::sum( j ... );
78 static constexpr int mysum ( std::integer_sequence< int > )
85 typedef std::tuple< BasisFunctionSets ... > BasisFunctionSetTupleType;
87 static_assert( Std::are_all_same<
typename BasisFunctionSets::DomainType ... >::value,
88 "TupleBasisFunctionSet needs common DomainType" );
90 typedef typename std::tuple_element< 0, BasisFunctionSetTupleType >::type::FunctionSpaceType ContainedFunctionSpaceType;
93 static const int dimDomain = ContainedFunctionSpaceType::dimDomain;
96 static const int setSize =
sizeof ... ( BasisFunctionSets );
97 static const int setIterationSize =
sizeof ... ( BasisFunctionSets )-1;
100 typedef std::array< std::size_t, setSize + 1 > OffsetType;
105 typedef std::tuple< std::vector< typename BasisFunctionSets::RangeType > ... > RangeStorageTupleType;
106 typedef std::tuple< std::vector< typename BasisFunctionSets::JacobianRangeType > ... > JacobianStorageTupleType;
107 typedef std::tuple< std::vector< typename BasisFunctionSets::HessianRangeType > ... > HessianStorageTupleType;
112 typename std::tuple_element< i, RangeStorageTupleType >::type
113 & rangeStorage()
const {
return std::get< i >( rangeStorage_ ); }
116 typename std::tuple_element< i, JacobianStorageTupleType >::type
117 & jacobianStorage()
const {
return std::get< i >( jacobianStorage_ ); }
120 typename std::tuple_element< i, HessianStorageTupleType >::type
121 & hessianStorage()
const {
return std::get< i >( hessianStorage_ ); }
124 mutable RangeStorageTupleType rangeStorage_;
125 mutable JacobianStorageTupleType jacobianStorage_;
126 mutable HessianStorageTupleType hessianStorage_;
132 typedef Indices< BasisFunctionSets::FunctionSpaceType::dimRange ... > RangeIndices;
135 template <
int dummy,
class CombOp>
136 struct CombinationTraits;
139 struct CombinationTraits< dummy, TupleSpaceProduct >
142 static constexpr const int dimRange = Std::sum(
static_cast< int >( BasisFunctionSets::FunctionSpaceType::dimRange ) ... );
145 typedef FunctionSpace<
typename ContainedFunctionSpaceType::DomainFieldType,
146 typename ContainedFunctionSpaceType::RangeFieldType,
149 template <
class ThisRange,
class Range>
150 static void apply(
const int rangeOffset,
const ThisRange& thisRange, Range& values)
153 std::copy( thisRange.begin(), thisRange.end(), values.begin() + rangeOffset );
157 static constexpr int rangeOffset ()
159 return RangeIndices::template offset< i >();
164 struct CombinationTraits< dummy, TupleSpaceSummation >
169 template <
class ThisRange,
class Range>
170 static void apply(
const int rangeOffset,
const ThisRange& thisRange, Range& values)
177 static constexpr int rangeOffset ()
184 typedef CombinationTraits< 0, CombineOp > CombinationType;
189 struct SubBasisFunctionSet
191 typedef typename std::tuple_element< i, BasisFunctionSetTupleType >::type type;
216 "TupleBasisFunctionSet needs common EntityType" );
218 typedef typename std::tuple_element< 0, BasisFunctionSetTupleType >::type::EntityType EntityType;
220 static_assert( Std::are_all_same<
typename BasisFunctionSets::ReferenceElementType ... >::value,
221 "TupleBasisFunctionSet needs ReferenceElementType" );
223 typedef typename std::tuple_element< 0, BasisFunctionSetTupleType >::type::ReferenceElementType ReferenceElementType;
226 TupleBasisFunctionSet () : offset_( {{ 0 }} ) {}
229 TupleBasisFunctionSet (
const BasisFunctionSets & ... basisFunctionSets )
230 : basisFunctionSetTuple_( basisFunctionSets ... ),
234 Fem::ForLoop< ComputeOffset, 0, setIterationSize >::apply( offset_, basisFunctionSetTuple_ );
238 TupleBasisFunctionSet (
const BasisFunctionSetTupleType &basisFunctionSetTuple )
239 : basisFunctionSetTuple_( basisFunctionSetTuple ),
243 Fem::ForLoop< ComputeOffset, 0, setIterationSize >::apply( offset_, basisFunctionSetTuple_ );
252 return order( std::index_sequence_for< BasisFunctionSets ... >() );
256 std::size_t
size ()
const
258 return size( std::index_sequence_for< BasisFunctionSets ... >() );
264 return std::get< 0 >( basisFunctionSetTuple_ ).type();
270 return std::get< 0 >( basisFunctionSetTuple_ ).valid();
274 const EntityType &entity ()
const
276 return std::get< 0 >( basisFunctionSetTuple_ ).entity();
282 return std::get< 0 >( basisFunctionSetTuple_ ).referenceElement();
286 template<
class Po
int,
class DofVector >
287 void evaluateAll (
const Point &x,
const DofVector &dofs, RangeType &value )
const
289 Fem::ForLoop< EvaluateAll, 0, setIterationSize >::apply( x, dofs, value, offset_, basisFunctionSetTuple_ );
293 template<
class Po
int,
class RangeArray >
294 void evaluateAll (
const Point &x, RangeArray &values )
const
296 assert( values.size() >=
size() );
297 Fem::ForLoop< EvaluateAllRanges, 0, setIterationSize >::apply( x, values, storage_, offset_, basisFunctionSetTuple_ );
301 template<
class QuadratureType,
class DofVector,
class RangeArray >
302 void evaluateAll (
const QuadratureType &quad,
const DofVector &dofs, RangeArray &ranges )
const
304 const int nop = quad.nop();
305 for(
int qp = 0; qp < nop; ++qp )
306 evaluateAll( quad[ qp ], dofs, ranges[ qp ] );
310 template<
class Po
int,
class DofVector >
311 void jacobianAll (
const Point &x,
const DofVector &dofs, JacobianRangeType &jacobian )
const
313 Fem::ForLoop< JacobianAll, 0, setIterationSize >::apply( x, dofs, jacobian, offset_, basisFunctionSetTuple_ );
317 template<
class Po
int,
class JacobianRangeArray >
318 void jacobianAll (
const Point &x, JacobianRangeArray &jacobians )
const
320 assert( jacobians.size() >=
size() );
321 Fem::ForLoop< JacobianAllRanges, 0, setIterationSize >::apply( x, jacobians, storage_, offset_, basisFunctionSetTuple_ );
325 template<
class QuadratureType,
class DofVector,
class JacobianArray >
326 void jacobianAll (
const QuadratureType &quad,
const DofVector &dofs, JacobianArray &jacobians )
const
328 const int nop = quad.nop();
329 for(
int qp = 0; qp < nop; ++qp )
330 jacobianAll( quad[ qp ], dofs, jacobians[ qp ] );
334 template<
class Po
int,
class DofVector >
335 void hessianAll (
const Point &x,
const DofVector &dofs, HessianRangeType &hessian )
const
337 Fem::ForLoop< HessianAll, 0, setIterationSize >::apply( x, dofs, hessian, offset_, basisFunctionSetTuple_ );
341 template<
class QuadratureType,
class DofVector,
class HessianArray >
342 void hessianAll (
const QuadratureType &quad,
const DofVector &dofs, HessianArray &hessians )
const
344 const int nop = quad.nop();
345 for(
int qp = 0; qp < nop; ++qp )
346 hessianAll( quad[ qp ], dofs, hessians[ qp ] );
350 template<
class Po
int,
class HessianRangeArray >
351 void hessianAll (
const Point &x, HessianRangeArray &hessians )
const
353 assert( hessians.size() >=
size() );
354 Fem::ForLoop< HessianAllRanges, 0, setIterationSize >::apply( x, hessians, storage_, offset_, basisFunctionSetTuple_ );
358 template<
class QuadratureType,
class Vector,
class DofVector >
359 void axpy (
const QuadratureType &quad,
const Vector &values, DofVector &dofs )
const
362 const unsigned int nop = quad.nop();
363 for(
unsigned int qp = 0; qp < nop; ++qp )
364 axpy( quad[ qp ], values[ qp ], dofs );
368 template<
class QuadratureType,
class VectorA,
class VectorB,
class DofVector >
369 void axpy (
const QuadratureType &quad,
const VectorA &valuesA,
const VectorB &valuesB, DofVector &dofs )
const
372 const unsigned int nop = quad.nop();
373 for(
unsigned int qp = 0; qp < nop; ++qp )
375 axpy( quad[ qp ], valuesA[ qp ], dofs );
376 axpy( quad[ qp ], valuesB[ qp ], dofs );
381 template<
class Po
int,
class DofVector >
382 void axpy (
const Point &x,
const RangeType &valueFactor, DofVector &dofs )
const
384 Fem::ForLoop< Axpy, 0, setIterationSize >::apply( x, valueFactor, dofs, offset_, basisFunctionSetTuple_ );
388 template<
class Po
int,
class DofVector >
389 void axpy (
const Point &x,
const JacobianRangeType &jacobianFactor, DofVector &dofs )
const
391 Fem::ForLoop< Axpy, 0, setIterationSize >::apply( x, jacobianFactor, dofs, offset_, basisFunctionSetTuple_ );
395 template<
class Po
int,
class DofVector >
396 void axpy (
const Point &x,
const HessianRangeType &hessianFactor, DofVector &dofs )
const
398 Fem::ForLoop< Axpy, 0, setIterationSize >::apply( x, hessianFactor, dofs, offset_, basisFunctionSetTuple_ );
402 template<
class Po
int,
class DofVector >
403 void axpy (
const Point &x,
const RangeType &valueFactor,
const JacobianRangeType &jacobianFactor, DofVector &dofs )
const
405 Fem::ForLoop< Axpy, 0, setIterationSize >::apply( x, valueFactor, jacobianFactor, dofs, offset_, basisFunctionSetTuple_ );
412 const typename SubBasisFunctionSet< i >::type& subBasisFunctionSet()
const
414 return std::get< i >( basisFunctionSetTuple_ );
418 std::size_t offset (
int i )
const
424 static int numSubBasisFunctionSets ()
431 template< std::size_t ... i >
432 int order ( std::index_sequence< i ... > )
const
434 return Std::max( std::get< i >( basisFunctionSetTuple_ ).order() ... );
438 template< std::size_t ... i >
439 std::size_t
size ( std::index_sequence< i ... > )
const
441 return Std::sum( std::get< i >( basisFunctionSetTuple_ ).
size() ... );
445 BasisFunctionSetTupleType basisFunctionSetTuple_;
456 template<
class CombineOp,
class ... BasisFunctionSets >
458 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
461 template<
class Tuple >
462 static void apply ( OffsetType &offset,
const Tuple &tuple )
464 offset[ i + 1 ] = offset[ i ] + std::get< i >( tuple ).size();
472 template<
class CombineOp,
class ... BasisFunctionSets >
474 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
478 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
480 template<
class Po
int,
class DofVector,
class Tuple >
481 static void apply (
const Point &x,
const DofVector &dofVector, RangeType &values,
const OffsetType &offset,
const Tuple &tuple )
484 std::size_t
size = std::get< i >( tuple ).size();
485 SubVector< const DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
486 typename std::tuple_element< i, BasisFunctionSetTupleType >::type::RangeType thisRange;
487 std::get< i >( tuple ).evaluateAll( x, subDofVector, thisRange );
490 CombinationType::apply( rangeOffset, thisRange, values );
498 template<
class CombineOp,
class ... BasisFunctionSets >
500 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
504 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
506 template<
class Po
int,
class DofVector,
class Tuple >
507 static void apply (
const Point &x,
const DofVector &dofVector, JacobianRangeType &values,
const OffsetType &offset,
const Tuple &tuple )
510 std::size_t
size = std::get< i >( tuple ).size();
511 SubVector< const DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
512 typename std::tuple_element< i, BasisFunctionSetTupleType >::type::JacobianRangeType thisJacobian;
513 std::get< i >( tuple ).jacobianAll( x, subDofVector, thisJacobian );
516 CombinationType::apply( rangeOffset, thisJacobian, values );
524 template<
class CombineOp,
class ... BasisFunctionSets >
526 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
530 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
532 template<
class Po
int,
class DofVector,
class Tuple >
533 static void apply (
const Point &x,
const DofVector &dofVector, HessianRangeType &values,
const OffsetType &offset,
const Tuple &tuple )
536 std::size_t
size = std::get< i >( tuple ).size();
537 SubVector< const DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
538 typename std::tuple_element< i, BasisFunctionSetTupleType >::type::HessianRangeType thisHessian;
539 std::get< i >( tuple ).hessianAll( x, subDofVector, thisHessian );
542 CombinationType::apply( rangeOffset, thisHessian, values );
550 template<
class CombineOp,
class ... BasisFunctionSets >
552 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
555 typedef typename std::tuple_element< i, typename Storage::RangeStorageTupleType >::type ThisStorage;
556 static const int thisDimRange = std::tuple_element< i, BasisFunctionSetTupleType >::type::FunctionSpaceType::dimRange;
559 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
561 template<
class Po
int,
class RangeArray,
class Tuple >
562 static void apply (
const Point &x, RangeArray &values,
const Storage &s,
const OffsetType &offset,
const Tuple &tuple )
564 std::size_t
size = std::get< i >( tuple ).size();
565 ThisStorage &thisStorage = s.template rangeStorage< i >();
566 thisStorage.resize(
size );
568 std::get< i >( tuple ).evaluateAll( x, thisStorage );
570 for( std::size_t j = 0; j <
size; ++j )
572 values[ j + offset[ i ] ] = RangeType( 0.0 );
573 for(
int r = 0; r < thisDimRange; ++r )
574 values[ j + offset[ i ] ][ r + rangeOffset ] = thisStorage[ j ][ r ];
583 template<
class CombineOp,
class ... BasisFunctionSets >
585 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
588 typedef typename std::tuple_element< i, typename Storage::JacobianStorageTupleType >::type ThisStorage;
589 static const int thisDimRange = std::tuple_element< i, BasisFunctionSetTupleType >::type::FunctionSpaceType::dimRange;
592 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
594 template<
class Po
int,
class RangeArray,
class Tuple >
595 static void apply (
const Point &x, RangeArray &values,
const Storage &s,
const OffsetType &offset,
const Tuple &tuple )
597 std::size_t
size = std::get< i >( tuple ).size();
598 ThisStorage &thisStorage = s.template jacobianStorage< i >();
599 thisStorage.resize(
size );
601 std::get< i >( tuple ).jacobianAll( x, thisStorage );
603 for( std::size_t j = 0; j <
size; ++j )
605 values[ j + offset[ i ] ] = JacobianRangeType( RangeFieldType( 0.0 ) );
606 for(
int r = 0; r < thisDimRange; ++r )
607 values[ j + offset[ i ] ][ r + rangeOffset ] = thisStorage[ j ][ r ];
616 template<
class CombineOp,
class ... BasisFunctionSets >
618 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
621 typedef typename std::tuple_element< i, typename Storage::HessianStorageTupleType >::type ThisStorage;
622 static const int thisDimRange = std::tuple_element< i, BasisFunctionSetTupleType >::type::FunctionSpaceType::dimRange;
625 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
627 template<
class Po
int,
class RangeArray,
class Tuple >
628 static void apply (
const Point &x, RangeArray &values,
const Storage &s,
const OffsetType &offset,
const Tuple &tuple )
630 std::size_t
size = std::get< i >( tuple ).size();
631 ThisStorage &thisStorage = s.template hessianStorage< i >();
632 thisStorage.resize(
size );
634 std::get< i >( tuple ).hessianAll( x, thisStorage );
636 for( std::size_t j = 0; j <
size; ++j )
638 values[ j + offset[ i ] ] =
typename HessianRangeType::value_type( 0.0 );
639 for(
int r = 0; r < thisDimRange; ++r )
640 values[ j + offset[ i ] ][ r + rangeOffset ] = thisStorage[ j ][ r ];
649 template<
class CombineOp,
class ... BasisFunctionSets >
651 struct TupleBasisFunctionSet< CombineOp, BasisFunctionSets ... >::
654 typedef typename std::tuple_element< i, BasisFunctionSetTupleType >::type::RangeType ThisRangeType;
655 typedef typename std::tuple_element< i, BasisFunctionSetTupleType >::type::JacobianRangeType ThisJacobianRangeType;
656 typedef typename std::tuple_element< i, BasisFunctionSetTupleType >::type::HessianRangeType ThisHessianRangeType;
659 static const int rangeOffset = CombinationType :: template rangeOffset< i >();
661 typedef SubObject< const RangeType, const ThisRangeType, rangeOffset > SubRangeType;
662 typedef SubObject< const JacobianRangeType, const ThisJacobianRangeType, rangeOffset > SubJacobianRangeType;
663 typedef SubObject< const HessianRangeType, const ThisHessianRangeType, rangeOffset > SubHessianRangeType;
666 template<
class Po
int,
class DofVector,
class Tuple >
667 static void apply (
const Point &x,
const RangeType &factor, DofVector &dofVector,
const OffsetType &offset,
const Tuple &tuple )
669 std::size_t
size = std::get< i >( tuple ).size();
670 SubVector< DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
671 SubRangeType subFactor( factor );
672 std::get< i >( tuple ).axpy( x, (ThisRangeType) subFactor, subDofVector );
676 template<
class Po
int,
class DofVector,
class Tuple >
677 static void apply (
const Point &x,
const JacobianRangeType &factor, DofVector &dofVector,
const OffsetType &offset,
const Tuple &tuple )
679 std::size_t
size = std::get< i >( tuple ).size();
680 SubVector< DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
681 SubJacobianRangeType subFactor( factor );
682 std::get< i >( tuple ).axpy( x, (ThisJacobianRangeType) subFactor, subDofVector );
686 template<
class Po
int,
class DofVector,
class Tuple >
687 static void apply (
const Point &x,
const HessianRangeType &factor, DofVector &dofVector,
const OffsetType &offset,
const Tuple &tuple )
689 std::size_t
size = std::get< i >( tuple ).size();
690 SubVector< DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
691 SubHessianRangeType subFactor( factor );
692 std::get< i >( tuple ).axpy( x, (ThisHessianRangeType) subFactor, subDofVector );
696 template<
class Po
int,
class DofVector,
class Tuple >
697 static void apply (
const Point &x,
const RangeType &rangeFactor,
const JacobianRangeType &jacobianFactor, DofVector &dofVector,
const OffsetType &offset,
const Tuple &tuple )
699 std::size_t
size = std::get< i >( tuple ).size();
700 SubVector< DofVector, OffsetSubMapper > subDofVector( dofVector, OffsetSubMapper(
size, offset[ i ] ) );
701 SubRangeType subRangeFactor( rangeFactor );
702 SubJacobianRangeType subJacobianFactor( jacobianFactor );
703 std::get< i >( tuple ).axpy( x, (ThisRangeType) subRangeFactor, (ThisJacobianRangeType) subJacobianFactor, subDofVector );
ImplementationDefined EntityType
entity type
Definition: basisfunctionsets.hh:29
Definition: explicitfieldvector.hh:75
FunctionSpaceTraits::RangeType RangeType
Type of range vector (using type of range field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:71
@ dimRange
dimension of range vector space
Definition: functionspaceinterface.hh:48
FunctionSpaceTraits::LinearMappingType JacobianRangeType
Intrinsic type used for the jacobian values has a Dune::FieldMatrix type interface.
Definition: functionspaceinterface.hh:75
FunctionSpaceTraits::DomainType DomainType
Type of domain vector (using type of domain field) has a Dune::FieldVector type interface.
Definition: functionspaceinterface.hh:67
FunctionSpaceTraits::RangeFieldType RangeFieldType
Intrinsic type used for values in the range field (usually a double)
Definition: functionspaceinterface.hh:63
A vector valued function space.
Definition: functionspace.hh:60
Unique label for each type of entities that can occur in DUNE grids.
Definition: type.hh:114
unspecified value type referenceElement(T &&... t)
Returns a reference element for the objects t....
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
A unique label for each type of element that can occur in a grid.