1 #ifndef DUNE_FEM_SPACE_COMBINEDSPACE_INTERPOLATION_HH
2 #define DUNE_FEM_SPACE_COMBINEDSPACE_INTERPOLATION_HH
3 
4 #include <tuple>
5 #include <utility>
6 
7 #include <dune/fem/common/forloop.hh>
8 #include <dune/fem/function/localfunction/converter.hh>
9 #include <dune/fem/space/basisfunctionset/tuple.hh>
10 #include <dune/fem/space/basisfunctionset/vectorial.hh>
11 #include <dune/fem/storage/subvector.hh>
12 
13 
14 namespace Dune
15 {
16 
17   namespace Fem
18   {
19 
20     // PowerSpaceInterpolation
21     // ------------------
22 
23     template< class Space, int N >
24     class PowerSpaceInterpolation
25     {
26       typedef PowerSpaceInterpolation< Space, N > ThisType;
27 
28       struct RangeConverter
29       {
RangeConverterDune::Fem::PowerSpaceInterpolation::RangeConverter30         RangeConverter ( std::size_t range ) : range_( range ) {}
31 
32         template< class T >
operator ()Dune::Fem::PowerSpaceInterpolation::RangeConverter33         FieldVector< T, 1 > operator() ( const FieldVector< T, N > &in ) const
34         {
35           return in[ range_ ];
36         }
37 
38         template< class T, int j >
operator ()Dune::Fem::PowerSpaceInterpolation::RangeConverter39         FieldMatrix< T, 1, j > operator() ( const FieldMatrix< T, N, j > &in ) const
40         {
41           return in[ range_ ];
42         }
43 
44       protected:
45         std::size_t range_;
46       };
47 
48       template <class DofVector, class DofAlignment>
49       struct SubDofVectorWrapper
50         : public SubDofVector< DofVector, DofAlignment >
51       {
52         typedef SubDofVector< DofVector, DofAlignment > BaseType;
53 
SubDofVectorWrapperDune::Fem::PowerSpaceInterpolation::SubDofVectorWrapper54         SubDofVectorWrapper( DofVector& dofs, int coordinate, const DofAlignment &dofAlignment )
55           : BaseType( dofs, coordinate, dofAlignment )
56         {}
57 
58         //! do nothing on clear since it's done in apply of this class
clearDune::Fem::PowerSpaceInterpolation::SubDofVectorWrapper59         void clear() {}
60       };
61 
62       // Note: BasisFunctionSetType is VectorialBasisFunctionSet
63       typedef typename Space::BasisFunctionSetType::DofAlignmentType DofAlignmentType;
64 
65     public:
66       typedef typename Space::EntityType EntityType;
67 
PowerSpaceInterpolation(const Space & space,const EntityType & entity)68       PowerSpaceInterpolation ( const Space &space, const EntityType &entity )
69         : interpolation_( space.containedSpace().localInterpolation( entity ) ),
70           dofAlignment_( space.basisFunctionSet( entity ).dofAlignment() )
71       {}
72 
73       template< class LocalFunction, class LocalDofVector >
operator ()(const LocalFunction & lv,LocalDofVector & ldv) const74       void operator () ( const LocalFunction &lv, LocalDofVector &ldv ) const
75       {
76         apply( lv, ldv );
77       }
78 
79       template< class LocalFunction, class LocalDofVector >
apply(const LocalFunction & lv,LocalDofVector & ldv) const80       void apply ( const LocalFunction &lv, LocalDofVector &ldv ) const
81       {
82         // clear dofs before something is adedd
83         ldv.clear();
84 
85         for( std::size_t i = 0; i < N; ++i )
86         {
87           SubDofVectorWrapper< LocalDofVector, DofAlignmentType > subLdv( ldv, i, dofAlignment_ );
88           interpolation_( localFunctionConverter( lv, RangeConverter( i ) ), subLdv );
89         }
90       }
91 
92     protected:
93       typename Space::ContainedDiscreteFunctionSpaceType::InterpolationImplType interpolation_;
94       DofAlignmentType dofAlignment_;
95     };
96 
97 
98     // TupleSpaceInterpolation
99     // -----------------------
100     // CombineOp describes the way in which the spaces have been combined, i.e.
101     // Product:    V = V_1 x V_2 x ...
102     // Summation:  V = V_1 + V_2 + ...
103 
104     template< class CombineOp , class ... Spaces >
105     class TupleSpaceInterpolation
106     {
107       typedef TupleSpaceInterpolation< CombineOp, Spaces ... > ThisType;
108       typedef std::tuple< typename Spaces::InterpolationImplType ... > InterpolationTupleType;
109 
110       static const int setSize = sizeof ... ( Spaces ) -1;
111 
112       template< int >
113       struct ProductApply;
114 
115       template< int >
116       struct SummationApply;
117 
118       template< int, class CombOp >
119       struct ApplyBase;
120 
121       template< int counter >
122       struct ApplyBase< counter, TupleSpaceProduct > : public ProductApply< counter >{};
123 
124       template< int counter >
125       struct ApplyBase< counter, TupleSpaceSummation > : public SummationApply< counter >{};
126 
127       template < int counter >
128       struct Apply : public ApplyBase< counter, CombineOp > {};
129 
130       typedef TupleBasisFunctionSet< CombineOp, typename Spaces::BasisFunctionSetType ... >   BasisFunctionSetType;
131 
132     public:
133 
134       static_assert( Std::are_all_same< typename Spaces::EntityType ... >::value,
135                      "TupleSpaceInterpolation requires Spaces defined over the same grid" );
136 
137       typedef typename std::tuple_element< 0, std::tuple< Spaces ... > >::type::EntityType EntityType;
138 
TupleSpaceInterpolation(std::tuple<const Spaces &...> tuple,const EntityType & entity)139       TupleSpaceInterpolation ( std::tuple< const Spaces & ... > tuple, const EntityType &entity )
140         : interpolation_( interpolationTuple( tuple, entity ) ),
141           basisFunctionSet_( basisFunctionSetTuple( tuple, entity ) )
142       {}
143 
TupleSpaceInterpolation(const Spaces &...spaces,const EntityType & entity)144       TupleSpaceInterpolation ( const Spaces & ... spaces, const EntityType &entity )
145         : interpolation_( std::make_tuple( spaces.localInterpolation( entity ) ... ) ),
146           basisFunctionSet_( std::make_tuple( spaces.basisFunctionSet( entity ) ... )  )
147       {}
148 
149       template< class LocalFunction, class LocalDofVector >
operator ()(const LocalFunction & lf,LocalDofVector & ldv) const150       void operator() ( const LocalFunction &lf, LocalDofVector &ldv ) const
151       {
152         Fem::ForLoop< Apply, 0, setSize >::apply( interpolation_, basisFunctionSet_, lf, ldv );
153       }
154 
unbind()155       void unbind() {}
156 
157     protected:
158       InterpolationTupleType interpolation_;
159       BasisFunctionSetType basisFunctionSet_;
160     };
161 
162 
163     // specialization of TupleSpaceInterpolation::Apply for SpaceProduct
164     template< class CombineOp, class ... Spaces >
165     template< int i >
166     struct TupleSpaceInterpolation< CombineOp, Spaces ... >::ProductApply
167     {
168       static const int rangeOffset = BasisFunctionSetType::RangeIndices::template offset< i >();
169       static const int thisDimRange = BasisFunctionSetType::template SubBasisFunctionSet< i >::type::FunctionSpaceType::dimRange;
170       static const int dimRange = BasisFunctionSetType::FunctionSpaceType::dimRange;
171 
172       struct RangeConverter
173       {
174         template< class T >
operator ()Dune::Fem::TupleSpaceInterpolation::ProductApply::RangeConverter175         FieldVector< T, thisDimRange > operator() ( const FieldVector< T, dimRange > &in ) const
176         {
177           FieldVector< T, thisDimRange > ret;
178           apply( in, ret );
179           return ret;
180         }
181 
182         template< class T, int j >
operator ()Dune::Fem::TupleSpaceInterpolation::ProductApply::RangeConverter183         FieldMatrix< T, thisDimRange, j > operator() ( const FieldMatrix< T, dimRange, j > &in ) const
184         {
185           FieldMatrix< T, thisDimRange, j > ret;
186           apply( in, ret );
187           return ret;
188         }
189 
190       protected:
191         template< class In, class Out >
applyDune::Fem::TupleSpaceInterpolation::ProductApply::RangeConverter192         void apply ( const In &in, Out &out ) const
193         {
194           for( std::size_t j = 0; j < thisDimRange; ++j )
195             out[ j ] = in[ j + rangeOffset ];
196         }
197       };
198 
199       template< class Tuple, class LocalFunction, class LocalDofVector >
applyDune::Fem::TupleSpaceInterpolation::ProductApply200       static void apply ( const Tuple &tuple, const BasisFunctionSetType &basisSet, const LocalFunction &lv, LocalDofVector &ldv )
201       {
202         SubVector< LocalDofVector, OffsetSubMapper >
203           subLdv( ldv, OffsetSubMapper( basisSet.template subBasisFunctionSet< i >().size(), basisSet.offset( i ) ) );
204         std::get< i >( tuple ) ( localFunctionConverter( lv, RangeConverter() ), subLdv );
205       }
206     };
207 
208 
209     template< class CombineOp, class ... Spaces >
210     template< int i >
211     struct TupleSpaceInterpolation< CombineOp, Spaces ... >::SummationApply
212     {
213       template< class Tuple, class LocalFunction, class LocalDofVector >
applyDune::Fem::TupleSpaceInterpolation::SummationApply214       static void apply ( const Tuple &tuple, const BasisFunctionSetType &basisSet, const LocalFunction &lv, LocalDofVector &ldv )
215       {
216         SubVector< LocalDofVector, OffsetSubMapper >
217           subLdv( ldv, OffsetSubMapper( basisSet.template subBasisFunctionSet< i >().size(), basisSet.offset( i ) ) );
218         std::get< i >( tuple ) ( lv,  subLdv );
219       }
220     };
221 
222   } // namespace Fem
223 
224 } // namespace Dune
225 
226 #endif // #ifndef DUNE_FEM_SPACE_COMBINEDSPACE_INTERPOLATION_HH
227