1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 sw=2 sts=2:
3 
4 #ifndef DUNE_PDELAB_GRIDFUNCTIONSPACE_TAGS_HH
5 #define DUNE_PDELAB_GRIDFUNCTIONSPACE_TAGS_HH
6 
7 #include <dune/grid/common/gridenums.hh>
8 #include <dune/typetree/utility.hh>
9 
10 #include <dune/pdelab/common/dofindex.hh>
11 #include <dune/pdelab/common/simpledofindex.hh>
12 
13 #include <numeric>
14 
15 namespace Dune {
16   namespace PDELab {
17 
18     //! \addtogroup GridFunctionSpace
19     //! \ingroup PDELab
20     //! \{
21 
22     struct FunctionSpaceTag {};
23 
24     struct GridFunctionSpaceTag : public FunctionSpaceTag {};
25 
26     struct PowerGridFunctionSpaceTag : public GridFunctionSpaceTag {};
27 
28     struct VectorGridFunctionSpaceTag : public PowerGridFunctionSpaceTag {};
29 
30     struct CompositeGridFunctionSpaceTag : public GridFunctionSpaceTag {};
31 
32     struct LeafGridFunctionSpaceTag : public GridFunctionSpaceTag {};
33 
34     template<typename ProxiedGFSTag>
35     struct GridFunctionSubSpaceTag
36       : public ProxiedGFSTag
37     {};
38 
39     //! Tag for the intermediate base class of the CompositeGridFunctionSpace.
40     struct CompositeGridFunctionSpaceBaseTag {};
41 
42     //! \brief Indicate blocking of the unknowns by grid entity.
43     /**
44      * This class instructs the non-leaf GridFunctionSpaces to block the dofs
45      * of the child-GridFunctionSpaces by grid entity, i.e. first all dofs of
46      * all children that belong to vertex 0, then all dofs associated with vertex
47      * 1 etc.
48      *
49      * The EntityBlockedOrdering correctly handles different block sizes for different
50      * GeometryTypes as well as GridFunctionSpaces with variable sizes, e.g. for
51      * $p$-adaptivity and in a MultiDomain context.
52      */
53     struct EntityBlockedOrderingTag {};
54 
55     //! \brief Indicate lexicographic ordering of the unknowns of non-leaf
56     //!        grid function spaces.
57     /**
58      * This class instructs the non-leaf GridFunctionSpaces to order the dofs
59      * of the child-GridFunctionSpaces in a lexicographic manner in the
60      * combined dof-vector, i.e. first all dofs of child 0, then all dofs of
61      * child 1 and so on.
62      */
63     struct LexicographicOrderingTag { };
64 
65     //! \brief Indicate interleaved ordering of the unknowns of non-leaf
66     //!        grid function spaces according to a given blocking pattern.
67     /**
68      * This class instructs the non-leaf GridFunctionSpaces to order the dofs
69      * of the child-GridFunctionSpaces in an interleaved manner in the
70      * combined dof-vector. The sizes of the individual blocks have to be passed
71      * to the constructor of the tag.
72      *
73      * \note In the vast majority of scenarios, you will want to use the
74      *       EntityBlockedOrderingTag instead of this one, as it is much less error-prone
75      *       and works in a wider variety of settings. Only use the InterleavedOrderingTag
76      *       if you know that the EntityBlockedOrderingTag will not work for you!
77      */
78     struct InterleavedOrderingTag
79     {
80 
81       //! Constructs an InterleavedOrderingTag with a block structure given by the initializer list sizes.
82       /**
83        * If you have a sufficiently recent compiler, this constructor enables a much more readable
84        * syntax when creating a GridFunctionSpace. Assuming that GFS is a PowerGridFunctionSpace and VBE its
85        * associated vector backend, you can shorten the verbose
86        *
87        * \code
88        * std::vector<std::size_t> sizes(3);
89        * sizes[0] = 2;
90        * sizes[1] = 5;
91        * sizes[2] = 3;
92        * GFS gfs(child_gfs,VBE(),InterleavedOrderingTag(sizes));
93        * \endcode
94        *
95        * to the much shorter and more readable
96        *
97        * \code
98        * GFS gfs(child_gfs,VBE(),{2,5,3});
99        * \endcode
100        */
InterleavedOrderingTagDune::PDELab::InterleavedOrderingTag101       InterleavedOrderingTag(std::initializer_list<std::size_t> sizes)
102         : _offsets(sizes.size() + 1,0)
103       {
104         std::partial_sum(sizes.begin(),sizes.end(),_offsets.begin() + 1);
105       }
106 
107       //! Constructs an InterleavedOrderingTag with a block structure given by the std::vector sizes.
InterleavedOrderingTagDune::PDELab::InterleavedOrderingTag108       InterleavedOrderingTag(std::vector<std::size_t> sizes)
109         : _offsets(sizes.size() + 1,0)
110       {
111         std::partial_sum(sizes.begin(),sizes.end(),_offsets.begin() + 1);
112       }
113 
114       //! Returns a list of offsets for the child blocks.
offsetsDune::PDELab::InterleavedOrderingTag115       const std::vector<std::size_t>& offsets() const
116       {
117         return _offsets;
118       }
119 
120     private:
121 
122       std::vector<std::size_t> _offsets;
123     };
124 
125     //! Mixin indicating whether a leaf GridFunctionSpace should never assume a const ordering size.
126     template<bool v>
127     struct NoConstOrderingSize
128     {
129       static const bool no_const_ordering_size = v;
130     };
131 
132     namespace {
133 
134       // Use this compile-time bridge to shup up GCC warnings
135 
136       template<int i>
137       struct shift_if_nonnegative
138       {
139         static const unsigned int value = 1 << i;
140       };
141 
142       template<>
143       struct shift_if_nonnegative<-1>
144       {
145         static const unsigned int value = 0;
146       };
147 
148     }
149 
150     //! Helper for building the bitmask describing the grid partitions contained in a GFS.
151     /**
152      * This struct should be used to construct the bitmask for use by the
153      * PartitionInfoProvider.
154      */
155     template<int p0 = -1, int p1 = -1, int p2 = -1, int p3 = -1, int p4 = -1>
156     struct PartitionSelector
157     {
158 
159       static const unsigned int partition_mask =
160         shift_if_nonnegative<p0>::value |
161         shift_if_nonnegative<p1>::value |
162         shift_if_nonnegative<p2>::value |
163         shift_if_nonnegative<p3>::value |
164         shift_if_nonnegative<p4>::value;
165 
166     };
167 
168     struct EmptyParams
169     {};
170 
171     //! Tag indicating a standard ordering for a leaf GridfunctionSpace.
172     /**
173      * Any additional policies regarding the ordering should be passed via
174      * the template parameter Params. By itself, this tag indicates that the
175      * user wants to use the standard, MultiIndex-based ordering infrastructure
176      * for this GridFunctionSpace.
177      *
178      * \tparam Params  Parameter struct for passing additional static information
179      *                 to the ordering. This parameter will become the base class
180      *                 of the tag.
181      */
182     template<typename Params>
183     struct LeafOrderingTag
184       : public Params
185     {};
186 
187     using DefaultLeafOrderingTag = LeafOrderingTag<EmptyParams>;
188 
189     //! Tag indicating a function space with a single unknown attached to every
190     //! entity of a exactly one single codimension.
191     struct SingleCodimMapper {};
192 
193     //! Tag denoting a PowerLocalFunctionSpace
194     struct PowerLocalFunctionSpaceTag {};
195 
196     //! Tag denoting a CompositeLocalFunctionSpace
197     struct CompositeLocalFunctionSpaceTag {};
198 
199     //! Tag denoting a LeafLocalFunctionSpace
200     struct LeafLocalFunctionSpaceTag {};
201 
202     //! Tag for denoting possibly nested containers, requiring a recursive
203     //! allocation algorithm.
204     struct HierarchicContainerAllocationTag {};
205 
206     //! Tag for denoting that a backend / ordering will always spawn flat
207     //! containers.
208     struct FlatContainerAllocationTag {};
209 
210     //! Tag denoting that an ordering will work with the default implementation
211     //! of the LFSIndexCache.
212     struct DefaultLFSCacheTag {};
213 
214     //! Tag denoting that an ordering will work with the simplified version of
215     //! the LFSIndexCache.
216     struct SimpleLFSCacheTag {};
217 
218     namespace Experimental {
219 
220       struct DuneFunctionsCacheTag {};
221 
222     }
223 
224     template<typename GFS, typename Tag>
225     struct _build_dof_index_type
226     {
227       typedef Dune::PDELab::DOFIndex<std::size_t,TypeTree::TreeInfo<GFS>::depth,2> type;
228     };
229 
230     template<typename GFS>
231     struct _build_dof_index_type<GFS,SingleCodimMapper>
232     {
233       typedef SimpleDOFIndex<typename GFS::Traits::SizeType> type;
234     };
235 
236 
237     template<typename GFS>
238     struct build_dof_index_type
239     {
240       typedef typename _build_dof_index_type<GFS,typename GFS::OrderingTag>::type type;
241     };
242 
243 
244 #ifndef DOXYGEN
245 
246     //! GridFunctionSpace to LocalFunctionSpace transformation.
247     /**
248      * gfs_to_lfs describes the transformation of a GridFunctionSpace tree to its corresponding
249      * LocalFunctionSpace tree and holds any information that may be required for performing
250      * the transformation.
251      *
252      * \warning The exact meaning of the template parameter is an implementation detail
253      *          and may change at any time, as the only class that is supposed to instantiate
254      *          the transformation is LocalFunctionSpace. Implementors of custom transformation
255      *          descriptors should only use information exported by gfs_to_lfs. In particular,
256      *          the registration declaration should not make any assumptions on GFS and just
257      *          treat it as some kind of opaque parameter type.
258      *
259      * \tparam GFS  the root GridFunctionSpace that the resulting LocalFunctionSpace tree
260      *              will be based on.
261      */
262     template<typename GFS>
263     struct gfs_to_lfs {
264 
265       //! The MultiIndex type that will be used in the resulting LocalFunctionSpace tree.
266       //typedef Dune::PDELab::MultiIndex<std::size_t,TypeTree::TreeInfo<GFS>::depth> MultiIndex;
267       typedef typename build_dof_index_type<GFS>::type DOFIndex;
268 
269     };
270 
271 #endif // DOXYGEN
272 
273     //! \} group GridFunctionSpace
274   } // namespace PDELab
275 } // namespace Dune
276 
277 #endif // DUNE_PDELAB_GRIDFUNCTIONSPACE_TAGS_HH
278