dune-pdelab  2.7-git
gridfunctionspacebase.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_PDELAB_GRIDFUNCTIONSPACE_GRIDFUNCTIONSPACEBASE_HH
4 #define DUNE_PDELAB_GRIDFUNCTIONSPACE_GRIDFUNCTIONSPACEBASE_HH
5 
6 #include <optional>
7 
8 #include <dune/typetree/visitor.hh>
9 #include <dune/typetree/traversal.hh>
10 
12 
13 namespace Dune {
14  namespace PDELab {
15 
19 
20 #ifndef DOXYGEN
21 
22  // forward declaration for friend declaration
23  template<typename GFS, typename GFSTraits>
24  class GridFunctionSpaceBase;
25 
26  namespace impl {
27 
28  struct reset_root_space_flag
29  : public TypeTree::DirectChildrenVisitor
30  , public TypeTree::DynamicTraversal
31  {
32 
33  template<typename GFS, typename Child, typename TreePath, typename ChildIndex>
34  void afterChild(const GFS& gfs, Child& child, TreePath, ChildIndex) const
35  {
36  if (child._initialized && child._is_root_space)
37  {
38  DUNE_THROW(GridFunctionSpaceHierarchyError,"initialized space cannot become part of larger GridFunctionSpace tree");
39  }
40  child._is_root_space = false;
41  }
42 
43  };
44 
45  template<typename size_type>
46  struct update_ordering_data;
47 
48  // helper class with minimal dependencies. Orderings keep a pointer to this structure and populate it
49  // during their update procedure.
50 
51  template<typename size_type>
52  class GridFunctionSpaceOrderingData
53  {
54 
55  template<typename,typename>
56  friend class ::Dune::PDELab::GridFunctionSpaceBase;
57 
58  template<typename>
59  friend struct update_ordering_data;
60 
61  GridFunctionSpaceOrderingData()
62  : _size(0)
63  , _block_count(0)
64  , _global_size(0)
65  , _max_local_size(0)
66  , _is_root_space(true)
67  , _initialized(false)
68  , _size_available(true)
69  {}
70 
71  size_type _size;
72  size_type _block_count;
73  size_type _global_size;
74  size_type _max_local_size;
75  bool _is_root_space;
76  bool _initialized;
77  bool _size_available;
78 
79  };
80 
81  template<typename size_type>
82  struct update_ordering_data
83  : public TypeTree::TreeVisitor
84  , public TypeTree::DynamicTraversal
85  {
86 
87  typedef GridFunctionSpaceOrderingData<size_type> Data;
88 
89  template<typename Ordering>
90  void update(const Ordering& ordering, bool is_root)
91  {
92  if (ordering._gfs_data)
93  {
94  Data& data = *ordering._gfs_data;
95  // if (data._initialized && data._is_root_space && !is_root)
96  // {
97  // DUNE_THROW(GridFunctionSpaceHierarchyError,"former root space is now part of a larger tree");
98  // }
99  data._initialized = true;
100  data._global_size = _global_size;
101  data._max_local_size = _max_local_size;
102  data._size_available = ordering.update_gfs_data_size(data._size,data._block_count);
103  }
104  }
105 
106  template<typename Ordering, typename TreePath>
107  void leaf(const Ordering& ordering, TreePath tp)
108  {
109  update(ordering,tp.size() == 0);
110  }
111 
112  template<typename Ordering, typename TreePath>
113  void post(const Ordering& ordering, TreePath tp)
114  {
115  update(ordering,tp.size() == 0);
116  }
117 
118  template<typename Ordering>
119  explicit update_ordering_data(const Ordering& ordering)
120  : _global_size(ordering.size())
121  , _max_local_size(ordering.maxLocalSize())
122  {}
123 
124  const size_type _global_size;
125  const size_type _max_local_size;
126 
127  };
128 
129 
131  template<class EntitySet>
132  struct common_entity_set
133  : public TypeTree::TreeVisitor
134  , public TypeTree::DynamicTraversal
135  {
136  template<typename T, typename TreePath>
137  void leaf(T&& t, TreePath treePath) {
138  if (not _entity_set)
139  _entity_set = t.entitySet();
140  else if (*_entity_set != t.entitySet())
141  DUNE_THROW(
142  GridFunctionSpaceHierarchyError,
143  "Use same entity sets for every space that is entity blocked! "
144  "A reason for getting this error is creating GridFunctionSpaces with "
145  "a grid view in the constructor. To solve this, create an entity set"
146  "(e.g. AllEntitySet<GV>) and use one instance to construct all of your GridFunctionSpaces."
147 );
148  }
149 
150  std::optional<EntitySet> _entity_set;
151  };
152 
158  template<class EntitySet>
159  struct update_leaf_entity_set
160  : public TypeTree::TreeVisitor
161  , public TypeTree::DynamicTraversal
162  {
163  update_leaf_entity_set(const std::optional<EntitySet>& entity_set, bool force_update)
164  : _force_update{force_update}
165  , _entity_set{entity_set}
166  {}
167 
168  template<typename GFSNode, typename TreePath>
169  void leaf(GFSNode&& gfs_node, TreePath treePath) {
170  if (not _entity_set)
171  _entity_set = gfs_node.entitySet();
172  if (*_entity_set != gfs_node.entitySet()) {
173  gfs_node.entitySet().update(_force_update);
174  _entity_set = gfs_node.entitySet();
175  }
176  }
177 
178  bool _force_update;
179  std::optional<EntitySet> _entity_set;
180  };
181 
182  } // namespace impl
183 
184 #endif // DOXYGEN
185 
186 
187  template<typename GFS, typename GFSTraits>
189  : public impl::GridFunctionSpaceOrderingData<typename GFSTraits::SizeType>
190  {
191 
192  friend struct impl::reset_root_space_flag;
193 
194  public:
195 
196  typedef GFSTraits Traits;
197 
198  template<typename Backend_, typename OrderingTag_>
199  GridFunctionSpaceBase(Backend_&& backend, OrderingTag_&& ordering_tag)
200  : _backend(std::forward<Backend_>(backend))
201  , _ordering_tag(std::forward<OrderingTag_>(ordering_tag))
202  {
203  TypeTree::applyToTree(gfs(),impl::reset_root_space_flag());
204  }
205 
206  typename Traits::SizeType size() const
207  {
208  if (!_initialized)
209  {
210  DUNE_THROW(UninitializedGridFunctionSpaceError,"space is not initialized");
211  }
212  if (!_size_available)
213  {
215  "Size cannot be calculated at this point in the GFS tree.");
216  }
217  return _size;
218  }
219 
220  typename Traits::SizeType blockCount() const
221  {
222  if (!_initialized)
223  {
224  DUNE_THROW(UninitializedGridFunctionSpaceError,"space is not initialized");
225  }
226  if (!_size_available)
227  {
229  "Block count cannot be calculated at this point in the GFS tree.");
230  }
231  return _block_count;
232  }
233 
234  typename Traits::SizeType globalSize() const
235  {
236  if (!_initialized)
237  {
238  DUNE_THROW(UninitializedGridFunctionSpaceError,"space is not initialized");
239  }
240  return _global_size;
241  }
242 
244  typename Traits::SizeType maxLocalSize () const
245  {
246  if (!_initialized)
247  {
248  DUNE_THROW(UninitializedGridFunctionSpaceError,"space is not initialized");
249  }
250  return _max_local_size;
251  }
252 
254 
259  void update(bool force = false)
260  {
261  gfs().entitySet().update(force);
262  auto update_leaf_es = impl::update_leaf_entity_set{_entity_set, force};
263  TypeTree::applyToTree(gfs(), update_leaf_es);
264  // We bypass the normal access using ordering() here to avoid a double
265  // update if the Ordering has not been created yet.
266  if (!gfs()._ordering)
267  gfs().create_ordering();
268  update(*gfs()._ordering);
269  }
270 
271  const std::string& name() const
272  {
273  return _name;
274  }
275 
276  void name(const std::string& name)
277  {
278  _name = name;
279  }
280 
281  typename Traits::Backend& backend()
282  {
283  return _backend;
284  }
285 
286  const typename Traits::Backend& backend() const
287  {
288  return _backend;
289  }
290 
292  const typename Traits::GridView& gridView () const
293  {
294  return gfs().entitySet().gridView();
295  }
296 
298  const typename Traits::EntitySet& entitySet () const
299  {
300  assert(_entity_set && "No entity set has been assigned to this node");
301  return *_entity_set;
302  }
303 
305  typename Traits::EntitySet& entitySet ()
306  {
307  assert(_entity_set && "No entity set has been assigned to this node");
308  return *_entity_set;
309  }
310 
311 
327  void setEntitySet(typename Traits::EntitySet entity_set)
328  {
329  _entity_set.emplace(std::move(entity_set));
330  }
331 
332  typename Traits::OrderingTag& orderingTag()
333  {
334  return _ordering_tag;
335  }
336 
337  const typename Traits::OrderingTag& orderingTag() const
338  {
339  return _ordering_tag;
340  }
341 
342  bool isRootSpace() const
343  {
344  return _is_root_space;
345  }
346 
347  protected:
348 
349  template<typename Ordering>
350  void update(Ordering& ordering) const
351  {
352  if (!_is_root_space)
353  {
354  DUNE_THROW(GridFunctionSpaceHierarchyError,"update() may only be called on the root of the function space hierarchy");
355  }
356  ordering.update();
357  TypeTree::applyToTree(ordering,impl::update_ordering_data<typename Traits::SizeType>(ordering));
358  }
359 
360  mutable std::optional<typename Traits::EntitySet> _entity_set;
361 
362  private:
363 
364  typedef impl::GridFunctionSpaceOrderingData<typename GFSTraits::SizeType> BaseT;
365 
366  GFS& gfs()
367  {
368  return static_cast<GFS&>(*this);
369  }
370 
371  const GFS& gfs() const
372  {
373  return static_cast<const GFS&>(*this);
374  }
375 
376  std::string _name;
377  typename Traits::Backend _backend;
378  typename Traits::OrderingTag _ordering_tag;
379 
380  using BaseT::_size;
381  using BaseT::_block_count;
382  using BaseT::_global_size;
383  using BaseT::_max_local_size;
384  using BaseT::_is_root_space;
385  using BaseT::_initialized;
386  using BaseT::_size_available;
387 
388  };
389 
390 
391  } // namespace PDELab
392 } // namespace Dune
393 
394 #endif // DUNE_PDELAB_GRIDFUNCTIONSPACE_GRIDFUNCTIONSPACEBASE_HH
PDELab-specific exceptions.
void update(Ordering &ordering) const
Definition: gridfunctionspacebase.hh:350
GFSTraits Traits
Definition: gridfunctionspacebase.hh:196
Traits::SizeType maxLocalSize() const
get max dimension of shape function space
Definition: gridfunctionspacebase.hh:244
const Traits::GridView & gridView() const
get grid view
Definition: gridfunctionspacebase.hh:292
Traits::Backend & backend()
Definition: gridfunctionspacebase.hh:281
const Traits::Backend & backend() const
Definition: gridfunctionspacebase.hh:286
Traits::SizeType blockCount() const
Definition: gridfunctionspacebase.hh:220
std::optional< typename Traits::EntitySet > _entity_set
Definition: gridfunctionspacebase.hh:360
void setEntitySet(typename Traits::EntitySet entity_set)
Set the Entity Set object to this grid function space.
Definition: gridfunctionspacebase.hh:327
void name(const std::string &name)
Definition: gridfunctionspacebase.hh:276
Traits::OrderingTag & orderingTag()
Definition: gridfunctionspacebase.hh:332
const std::string & name() const
Definition: gridfunctionspacebase.hh:271
void update(bool force=false)
Update the indexing information of the GridFunctionSpace.
Definition: gridfunctionspacebase.hh:259
const Traits::EntitySet & entitySet() const
get entity set
Definition: gridfunctionspacebase.hh:298
const Traits::OrderingTag & orderingTag() const
Definition: gridfunctionspacebase.hh:337
Traits::SizeType globalSize() const
Definition: gridfunctionspacebase.hh:234
bool isRootSpace() const
Definition: gridfunctionspacebase.hh:342
Traits::SizeType size() const
Definition: gridfunctionspacebase.hh:206
Traits::EntitySet & entitySet()
get entity set
Definition: gridfunctionspacebase.hh:305
GridFunctionSpaceBase(Backend_ &&backend, OrderingTag_ &&ordering_tag)
Definition: gridfunctionspacebase.hh:199
For backward compatibility – Do not use this!
Definition: adaptivity.hh:28
Called a GridFunctionSpace method that requires initialization of the space.
Definition: exceptions.hh:30
Definition: gridfunctionspacebase.hh:190