AMDiS  2.10
The Adaptive Multi-Dimensional Simulation Toolbox
AdaptiveGrid.hpp
1 #pragma once
2 
3 #include <algorithm>
4 #include <list>
5 #include <memory>
6 #include <mutex>
7 #include <shared_mutex>
8 #include <type_traits>
9 #include <utility>
10 
11 #include <dune/common/hybridutilities.hh>
12 #include <dune/common/timer.hh>
13 #include <dune/common/version.hh>
14 #include <dune/common/parallel/mpihelper.hh>
15 
16 #include <dune/geometry/type.hh>
17 #include <dune/grid/common/backuprestore.hh>
18 #include <dune/grid/common/capabilities.hh>
19 #include <dune/grid/common/grid.hh>
20 #include <dune/grid/utility/structuredgridfactory.hh>
21 
22 #include <amdis/common/Concepts.hpp>
23 #include <amdis/common/DefaultGridView.hpp>
24 #include <amdis/common/SharedPtr.hpp>
25 #include <amdis/Observer.hpp>
26 #include <amdis/Output.hpp>
27 
28 namespace AMDiS
29 {
30  // forward declaration
31  template <class HostGrid>
33 
34 
37 
43  template <class HG>
45  : public Dune::GridDefaultImplementation<
46  HG::dimension, HG::dimensionworld, typename HG::ctype, AdaptiveGridFamily<HG> >
47  , public Notifier<event::preAdapt, event::adapt, event::postAdapt>
48  {
49  using Self = AdaptiveGrid<HG>;
50 
51  public:
52 
53  using HostGrid = HG;
55  using Traits = typename GridFamily::Traits;
56  using Element = typename Traits::template Codim<0>::Entity;
57 
58 
59  public:
60 
61  template <class HostGrid_,
62  Dune::disableCopyMove<Self, HostGrid_> = 0>
63  explicit AdaptiveGrid(HostGrid_&& hostGrid)
64  : hostGrid_(wrap_or_share(FWD(hostGrid)))
65  {}
66 
68  std::shared_ptr<HostGrid> const& hostGrid() const { return hostGrid_; }
69 
70 
71  public:
72 
75 
77  template <int codim, Dune::PartitionIteratorType pt = Dune::All_Partition>
78  auto lbegin(int level) const { return hostGrid_->levelGridView(level).template begin<codim,pt>(); }
79 
81  template <int codim, Dune::PartitionIteratorType pt = Dune::All_Partition>
82  auto lend(int level) const { return hostGrid_->levelGridView(level).template end<codim,pt>(); }
83 
84 
86  template <int codim, Dune::PartitionIteratorType pt = Dune::All_Partition>
87  auto leafbegin() const { return hostGrid_->leafGridView().template begin<codim,pt>(); }
88 
90  template <int codim, Dune::PartitionIteratorType pt = Dune::All_Partition>
91  auto leafend() const { return hostGrid_->leafGridView().template end<codim,pt>(); }
92 
93 
95  auto ilevelbegin(Element const& e) const { return hostGrid_->levelGridView(e.level()).ibegin(e); }
96 
98  auto ilevelend(Element const& e) const { return hostGrid_->levelGridView(e.level()).iend(e); }
99 
101  auto ileafbegin(Element const& e) const { return hostGrid_->leafGridView().ibegin(e); }
102 
104  auto ileafend(Element const& e) const { return hostGrid_->leafGridView().iend(e); }
105 
107 
108 
111 
113  int maxLevel() const { return hostGrid_->maxLevel(); }
114 
116  int size(int level, int codim) const { return hostGrid_->size(level, codim); }
117 
119  int size(int codim) const { return hostGrid_->size(codim); }
120 
122  int size(int level, Dune::GeometryType type) const { return hostGrid_->size(level, type); }
123 
125  int size(Dune::GeometryType type) const { return hostGrid_->size(type); }
126 
128  std::size_t numBoundarySegments() const { return hostGrid_->numBoundarySegments(); }
129 
131 
132 
135 
137  auto const& globalIdSet() const { return hostGrid_->globalIdSet(); }
138 
140  auto const& localIdSet() const { return hostGrid_->localIdSet(); }
141 
143  auto const& levelIndexSet(int level) const { return hostGrid_->levelIndexSet(level); }
144 
146  auto const& leafIndexSet() const { return hostGrid_->leafIndexSet(); }
147 
149 
150 
153 
155  void globalRefine(int refCount)
156  {
157  for (int i = 0; i < refCount; ++i) {
158  // mark all entities for grid refinement
159  for (const auto& element : elements(hostGrid_->leafGridView()))
160  hostGrid_->mark(1, element);
161  preAdapt();
162  adapt();
163  postAdapt();
164  }
165  }
166 
168  bool mark(int refCount, Element const& e) { return hostGrid_->mark(refCount, e); }
169 
171  int getMark(Element const& e) const { return hostGrid_->getMark(e); }
172 
174  bool preAdapt()
175  {
176  Dune::Timer t;
177  mightCoarsen_ = hostGrid_->preAdapt();
178  hostGrid_->comm().max(&mightCoarsen_, 1);
179  this->notify(event::preAdapt{mightCoarsen_});
180  info(2,"AdaptiveGrid::preAdapt needed {} seconds", t.elapsed());
181  return mightCoarsen_;
182  }
183 
185  bool adapt()
186  {
187  Dune::Timer t;
188  refined_ = hostGrid_->adapt();
189  hostGrid_->comm().max(&refined_, 1);
190  this->notify(event::adapt{mightCoarsen_ || refined_});
191  info(2,"AdaptiveGrid::adapt needed {} seconds", t.elapsed());
192  return refined_;
193  }
194 
196  void postAdapt()
197  {
198  Dune::Timer t;
199  hostGrid_->postAdapt();
200  this->notify(event::postAdapt{});
201  changeIndex_++;
202  info(2,"AdaptiveGrid::postAdapt needed {} seconds", t.elapsed());
203  }
204 
206  void update()
207  {
208  this->notify(event::adapt{true});
209  }
210 
212  unsigned long changeIndex() const
213  {
214  return changeIndex_;
215  }
216 
217  // @}
218 
219 
222 
224  auto const& comm() const { return hostGrid_->comm(); }
225 
227  template <class DataHandle>
228  void communicate(DataHandle& handle, Dune::InterfaceType iftype,
229  Dune::CommunicationDirection dir, int level) const
230  {
231  hostGrid_->levelGridView(level).communicate(handle,iftype,dir);
232  }
233 
235  template <class DataHandle>
236  void communicate(DataHandle& handle, Dune::InterfaceType iftype,
237  Dune::CommunicationDirection dir) const
238  {
239  hostGrid_->leafGridView().communicate(handle,iftype,dir);
240  }
241 
243 
248  bool loadBalance()
249  {
250  if constexpr (std::is_convertible_v<decltype(std::declval<HG>().loadBalance()), bool>)
251  return hostGrid_->loadBalance();
252  else {
253  hostGrid_->loadBalance();
254  return true;
255  }
256  }
257 
259 
266  template <class DataHandle>
267  bool loadBalance(DataHandle& handle)
268  {
269  if constexpr (std::is_convertible_v<decltype(std::declval<HG>().loadBalance(handle)), bool>)
270  return hostGrid_->loadBalance(handle);
271  else {
272  hostGrid_->loadBalance(handle);
273  return true;
274  }
275  }
276 
277 
279  int overlapSize(int level, int codim) const { return hostGrid_->levelGridView(level).overlapSize(codim); }
280 
282  int overlapSize(int codim) const { return hostGrid_->leafGridView().overlapSize(codim); }
283 
285  int ghostSize(int level, int codim) const { return hostGrid_->levelGridView(level).ghostSize(codim); }
286 
288  int ghostSize(int codim) const { return hostGrid_->leafGridView().ghostSize(codim); }
289 
291 
293  bool isLevelwiseConforming(int level) const
294  {
295  return hostGrid_->levelGridView(level).isConforming();
296  }
297 
299  bool isLeafwiseConforming() const
300  {
301  return hostGrid_->leafGridView().isConforming();
302  }
303 
304 
306  template <class EntitySeed>
307  auto entity(EntitySeed const& seed) const { return hostGrid_->entity(seed); }
308 
309 
310  private:
311 
313  std::shared_ptr<HostGrid> hostGrid_;
314 
317  bool mightCoarsen_ = false;
318 
320  bool refined_ = false;
321 
324  unsigned long changeIndex_ = 0;
325  };
326 
327  // deduction guide
328  template <class HostGrid>
329  AdaptiveGrid(HostGrid const&)
331 
332 
333  template <class HostGrid>
334  class AdaptiveGridFamily
335  {
336  template <class HG>
337  using CollectiveCommunication_t = typename HG::Traits::CollectiveCommunication;
338 
339  template <class HG>
340  using Communication_t = typename HG::Traits::Communication;
341 
342  public:
343  struct Traits : HostGrid::Traits
344  {
346  using CollectiveCommunication = Dune::Std::detected_t<CollectiveCommunication_t, HostGrid>;
347  using Communication = Dune::Std::detected_or_t<CollectiveCommunication, Communication_t, HostGrid>;
348  using LeafGridView = Dune::GridView< AMDiS::DefaultLeafGridViewTraits<const Grid> >;
349  using LevelGridView = Dune::GridView< AMDiS::DefaultLevelGridViewTraits<const Grid> >;
350  };
351  };
352 
353 
355  template <class HostGrid>
356  unsigned long changeIndex(HostGrid const& /*hostGrid*/)
357  {
358  return 0;
359  }
360 
362  template <class HostGrid>
363  unsigned long changeIndex(AdaptiveGrid<HostGrid> const& grid)
364  {
365  return grid.changeIndex();
366  }
367 
368 
369  namespace Impl
370  {
371  template <class HostGrid>
372  struct AdaptiveGridImpl
373  {
374  using type = AdaptiveGrid<HostGrid>;
375  };
376 
377  template <class HostGrid>
378  struct AdaptiveGridImpl<AdaptiveGrid<HostGrid>>
379  {
380  using type = AdaptiveGrid<HostGrid>;
381  };
382  }
383 
386  template <class HostGrid>
387  using AdaptiveGrid_t = typename Impl::AdaptiveGridImpl<HostGrid>::type;
388 
389 
390 } // end namespace AMDiS
391 
392 
393 namespace Dune
394 {
397  template <class HostGrid>
398  class GridFactory<AMDiS::AdaptiveGrid<HostGrid> >
399  : public GridFactoryInterface<AMDiS::AdaptiveGrid<HostGrid> >
400  {
401  using Self = GridFactory;
403  using GridType = AMDiS::AdaptiveGrid<HostGrid>;
404  using HostGridFactory = GridFactory<HostGrid>;
405 
406  public:
407 
408  using ctype = typename GridType::ctype;
409 
410  enum { dim = GridType::dimension };
411  enum { dimworld = GridType::dimensionworld };
412 
413  template <class... Args,
414  Dune::disableCopyMove<Self, Args...> = 0>
415  GridFactory(Args&&... args)
416  : hostFactory_(FWD(args)...)
417  {}
418 
420  void insertVertex(FieldVector<ctype,dimworld> const& pos) override
421  {
422  hostFactory_.insertVertex(pos);
423  }
424 
425  template <class F, class... Args>
426  using HasInsertElement = decltype(std::declval<F>().insertElement(std::declval<Args>()...));
427 
429  void insertElement(GeometryType const& type,
430  std::vector<unsigned int> const& vertices) override
431  {
432  hostFactory_.insertElement(type, vertices);
433  }
434 
435  using ElementParametrizationType
436  = std::function<FieldVector<ctype,dimworld>(FieldVector<ctype,dim>)>;
437 
439  void insertElement(GeometryType const& type,
440  std::vector<unsigned int> const& vertices,
441  ElementParametrizationType elementParametrization) override
442  {
443  using A0 = GeometryType;
444  using A1 = std::vector<unsigned int>;
445  using A2 = ElementParametrizationType;
446  if constexpr (Std::is_detected<HasInsertElement, HostGridFactory, A0,A1,A2>::value)
447  hostFactory_.insertElement(type, vertices, elementParametrization);
448  else
449  AMDiS::error_exit("insertElement() not implemented for HostGrid type.");
450  }
451  using Super::insertElement;
452 
453  template <class F, class... Args>
454  using HasInsertBoundarySegment = decltype(std::declval<F>().insertBoundarySegment(std::declval<Args>()...));
455 
457  void insertBoundarySegment(std::vector<unsigned int> const& vertices) override
458  {
459  hostFactory_.insertBoundarySegment(vertices);
460  }
461 
462  using BoundarySegmentType = std::shared_ptr<BoundarySegment<dim,dimworld> >;
463 
465  void insertBoundarySegment(std::vector<unsigned int> const& vertices,
466  BoundarySegmentType const& boundarySegment) override
467  {
468  using A0 = std::vector<unsigned int>;
469  using A1 = BoundarySegmentType;
470  if constexpr (Std::is_detected<HasInsertBoundarySegment, HostGridFactory, A0,A1>::value)
471  hostFactory_.insertBoundarySegment(vertices, boundarySegment);
472  else
473  AMDiS::error_exit("insertBoundarySegment() not implemented for HostGrid type.");
474  }
475 
477  std::unique_ptr<GridType> createGrid() override
478  {
479  std::unique_ptr<HostGrid> hostGrid(hostFactory_.createGrid());
480  return std::make_unique<GridType>(std::move(hostGrid));
481  }
482 
483  private:
484  HostGridFactory hostFactory_;
485  };
486 
487 
488  namespace Impl
489  {
490  template <class HostGrid, bool = Dune::Capabilities::hasBackupRestoreFacilities<HostGrid>::v>
491  class BackupRestoreFacilityImpl {};
492 
493  template <class HostGrid>
494  class BackupRestoreFacilityImpl<HostGrid,true>
495  {
497  using HostBackupRestoreFacility = BackupRestoreFacility<HostGrid>;
498 
499  public:
500 
502  template <class Output>
503  static void backup(Grid const& grid, Output const& filename_or_stream)
504  {
505  HostBackupRestoreFacility::backup(*grid.hostGrid(), filename_or_stream);
506  }
507 
509  template <class Input>
510  static Grid* restore(Input const& filename_or_stream)
511  {
512  std::unique_ptr<HostGrid> hostGrid(HostBackupRestoreFacility::restore(filename_or_stream));
513  return new Grid(std::move(hostGrid));
514  }
515  };
516 
517  } // end namespace Impl
518 
519 
522  template <class HostGrid>
523  class BackupRestoreFacility<AMDiS::AdaptiveGrid<HostGrid>>
524  : public Impl::BackupRestoreFacilityImpl<HostGrid>
525  {
526  public:
527  using Impl::BackupRestoreFacilityImpl<HostGrid>::BackupRestoreFacilityImpl;
528  };
529 
530 
531  namespace Capabilities
532  {
533  template <class HostGrid, int codim>
534  struct hasEntity<AMDiS::AdaptiveGrid<HostGrid>, codim>
535  : hasEntity<HostGrid,codim>{};
536 
537  template <class HostGrid, int codim>
538  struct hasEntityIterator<AMDiS::AdaptiveGrid<HostGrid>, codim>
539  : hasEntityIterator<HostGrid, codim> {};
540 
541  template <class HostGrid>
542  struct isLevelwiseConforming<AMDiS::AdaptiveGrid<HostGrid> >
543  : isLevelwiseConforming<HostGrid> {};
544 
545  template <class HostGrid>
546  struct isLeafwiseConforming<AMDiS::AdaptiveGrid<HostGrid> >
547  : isLeafwiseConforming<HostGrid> {};
548 
549  template <class HostGrid>
550  struct hasSingleGeometryType<AMDiS::AdaptiveGrid<HostGrid> >
551  : hasSingleGeometryType<HostGrid> {};
552 
553  template <class HostGrid, int codim >
554  struct canCommunicate<AMDiS::AdaptiveGrid<HostGrid>, codim>
555  : canCommunicate<HostGrid, codim> {};
556 
557  template <class HostGrid>
558  struct hasBackupRestoreFacilities<AMDiS::AdaptiveGrid<HostGrid> >
559  : hasBackupRestoreFacilities<HostGrid> {};
560 
561  template <class HostGrid>
562  struct threadSafe<AMDiS::AdaptiveGrid<HostGrid> >
563  : threadSafe<HostGrid> {};
564 
565  template <class HostGrid>
566  struct viewThreadSafe<AMDiS::AdaptiveGrid<HostGrid> >
567  : viewThreadSafe<HostGrid> {};
568 
569  } // end namespace Capabilities
570 } // end namespace Dune
void postAdapt()
Perform cleanup after grid adaptation and notify observers of the postAdapt event.
Definition: AdaptiveGrid.hpp:196
auto const & globalIdSet() const
Return const reference to the grids global id set.
Definition: AdaptiveGrid.hpp:137
auto ileafbegin(Element const &e) const
Obtain begin intersection iterator with respect to the leaf GridView.
Definition: AdaptiveGrid.hpp:101
bool isLeafwiseConforming() const
Return true if the leaf-grid view represents a conforming grid.
Definition: AdaptiveGrid.hpp:299
int overlapSize(int level, int codim) const
Return size of the overlap region for a given codim on the level grid view.
Definition: AdaptiveGrid.hpp:279
bool adapt()
Adapt the grid and notify observers of the adapt event.
Definition: AdaptiveGrid.hpp:185
auto leafbegin() const
Iterator to first leaf entity of given codim.
Definition: AdaptiveGrid.hpp:87
auto lend(int level) const
one past the end on this level
Definition: AdaptiveGrid.hpp:82
Definition: AdaptiveGrid.hpp:32
Definition: AdaptiveGrid.hpp:393
void update()
Update all registered dependent objects if grid is changed manually.
Definition: AdaptiveGrid.hpp:206
auto entity(EntitySeed const &seed) const
Obtain Entity from EntitySeed of the HostGrid.
Definition: AdaptiveGrid.hpp:307
auto ileafend(Element const &e) const
Obtain end intersection iterator with respect to the leaf GridView.
Definition: AdaptiveGrid.hpp:104
void communicate(DataHandle &handle, Dune::InterfaceType iftype, Dune::CommunicationDirection dir, int level) const
Communicate data of level gridView.
Definition: AdaptiveGrid.hpp:228
int size(int codim) const
Return number of leaf entities of a given codim in this process.
Definition: AdaptiveGrid.hpp:119
int overlapSize(int codim) const
Return size of the overlap region for a given codim on the leaf grid view.
Definition: AdaptiveGrid.hpp:282
Definition: AdaptiveGrid.hpp:343
bool mark(int refCount, Element const &e)
Marks an entity to be refined/coarsened in a subsequent adapt.
Definition: AdaptiveGrid.hpp:168
auto const & leafIndexSet() const
Return const reference to the host grids leaf index set.
Definition: AdaptiveGrid.hpp:146
Definition: AdaptBase.hpp:6
auto ilevelbegin(Element const &e) const
Obtain begin intersection iterator with respect to the level GridView.
Definition: AdaptiveGrid.hpp:95
int getMark(Element const &e) const
Return refinement mark for entity.
Definition: AdaptiveGrid.hpp:171
bool loadBalance(DataHandle &handle)
Calls loadBalance(handle) on the underlying grid.
Definition: AdaptiveGrid.hpp:267
int ghostSize(int codim) const
Return size of the ghost region for a given codim on the leaf grid view.
Definition: AdaptiveGrid.hpp:288
std::size_t numBoundarySegments() const
Returns the number of boundary segments within the macro grid.
Definition: AdaptiveGrid.hpp:128
auto leafend() const
One past the end of the sequence of leaf entities.
Definition: AdaptiveGrid.hpp:91
Definition: Observer.hpp:25
auto const & comm() const
Return const reference to a collective communication object.
Definition: AdaptiveGrid.hpp:224
bool loadBalance()
Calls loadBalance on the underlying grid.
Definition: AdaptiveGrid.hpp:248
auto const & levelIndexSet(int level) const
Return const reference to the host grids level index set for level level.
Definition: AdaptiveGrid.hpp:143
auto const & localIdSet() const
Return const reference to the host grids local id set.
Definition: AdaptiveGrid.hpp:140
int maxLevel() const
Return maximum level defined in this grid.
Definition: AdaptiveGrid.hpp:113
int size(Dune::GeometryType type) const
Return number of leaf entities per geometry type in this process.
Definition: AdaptiveGrid.hpp:125
Definition: Observer.hpp:30
auto ilevelend(Element const &e) const
Obtain end intersection iterator with respect to the level GridView.
Definition: AdaptiveGrid.hpp:98
unsigned long changeIndex() const
Returns the grid change index, see changeIndex.
Definition: AdaptiveGrid.hpp:212
Mixin for signaling of certain events.
Definition: Observer.hpp:54
int size(int level, Dune::GeometryType type) const
Return number of entities per level and geometry type in this process.
Definition: AdaptiveGrid.hpp:122
int ghostSize(int level, int codim) const
Return size of the ghost region for a given codim on the level grid view.
Definition: AdaptiveGrid.hpp:285
bool preAdapt()
Prepare the grid for adaptation and notify observers of the preAdapt event.
Definition: AdaptiveGrid.hpp:174
Wrapper class for Dune-grids that allows automatic signalling of events during grid adaptation...
Definition: AdaptiveGrid.hpp:44
void globalRefine(int refCount)
Refines all grid elements refCount times.
Definition: AdaptiveGrid.hpp:155
bool isLevelwiseConforming(int level) const
Return true if the level-rid view represents a conforming grid.
Definition: AdaptiveGrid.hpp:293
auto lbegin(int level) const
Iterator to first entity of given codim on level.
Definition: AdaptiveGrid.hpp:78
Definition: Observer.hpp:19
void communicate(DataHandle &handle, Dune::InterfaceType iftype, Dune::CommunicationDirection dir) const
Communicate data of leaf gridView.
Definition: AdaptiveGrid.hpp:236
std::shared_ptr< HostGrid > const & hostGrid() const
Return the underlying grid.
Definition: AdaptiveGrid.hpp:68
int size(int level, int codim) const
Number of grid entities per level and codim.
Definition: AdaptiveGrid.hpp:116