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
28namespace AMDiS
29{
30 // forward declaration
31 template <class HostGrid>
32 class AdaptiveGridFamily;
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
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
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
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&)
330 -> AdaptiveGrid<HostGrid>;
331
332
333 template <class HostGrid>
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
393namespace 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
Definition: AdaptiveGrid.hpp:335
Wrapper class for Dune-grids that allows automatic signalling of events during grid adaptation.
Definition: AdaptiveGrid.hpp:48
auto const & comm() const
Return const reference to a collective communication object.
Definition: AdaptiveGrid.hpp:224
void globalRefine(int refCount)
Refines all grid elements refCount times.
Definition: AdaptiveGrid.hpp:155
auto const & localIdSet() const
Return const reference to the host grids local id set.
Definition: AdaptiveGrid.hpp:140
auto ileafbegin(Element const &e) const
Obtain begin intersection iterator with respect to the leaf GridView.
Definition: AdaptiveGrid.hpp:101
void postAdapt()
Perform cleanup after grid adaptation and notify observers of the postAdapt event.
Definition: AdaptiveGrid.hpp:196
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
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
unsigned long changeIndex() const
Returns the grid change index, see changeIndex.
Definition: AdaptiveGrid.hpp:212
auto const & globalIdSet() const
Return const reference to the grids global id set.
Definition: AdaptiveGrid.hpp:137
auto lbegin(int level) const
Iterator to first entity of given codim on level.
Definition: AdaptiveGrid.hpp:78
void communicate(DataHandle &handle, Dune::InterfaceType iftype, Dune::CommunicationDirection dir) const
Communicate data of leaf gridView.
Definition: AdaptiveGrid.hpp:236
void communicate(DataHandle &handle, Dune::InterfaceType iftype, Dune::CommunicationDirection dir, int level) const
Communicate data of level gridView.
Definition: AdaptiveGrid.hpp:228
auto ilevelbegin(Element const &e) const
Obtain begin intersection iterator with respect to the level GridView.
Definition: AdaptiveGrid.hpp:95
bool mark(int refCount, Element const &e)
Marks an entity to be refined/coarsened in a subsequent adapt.
Definition: AdaptiveGrid.hpp:168
int ghostSize(int codim) const
Return size of the ghost region for a given codim on the leaf grid view.
Definition: AdaptiveGrid.hpp:288
int overlapSize(int codim) const
Return size of the overlap region for a given codim on the leaf grid view.
Definition: AdaptiveGrid.hpp:282
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 size(int level, int codim) const
Number of grid entities per level and codim.
Definition: AdaptiveGrid.hpp:116
auto entity(EntitySeed const &seed) const
Obtain Entity from EntitySeed of the HostGrid.
Definition: AdaptiveGrid.hpp:307
auto const & levelIndexSet(int level) const
Return const reference to the host grids level index set for level level.
Definition: AdaptiveGrid.hpp:143
bool preAdapt()
Prepare the grid for adaptation and notify observers of the preAdapt event.
Definition: AdaptiveGrid.hpp:174
auto leafbegin() const
Iterator to first leaf entity of given codim.
Definition: AdaptiveGrid.hpp:87
bool isLeafwiseConforming() const
Return true if the leaf-grid view represents a conforming grid.
Definition: AdaptiveGrid.hpp:299
int maxLevel() const
Return maximum level defined in this grid.
Definition: AdaptiveGrid.hpp:113
bool loadBalance()
Calls loadBalance on the underlying grid.
Definition: AdaptiveGrid.hpp:248
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
auto ileafend(Element const &e) const
Obtain end intersection iterator with respect to the leaf GridView.
Definition: AdaptiveGrid.hpp:104
void update()
Update all registered dependent objects if grid is changed manually.
Definition: AdaptiveGrid.hpp:206
auto const & leafIndexSet() const
Return const reference to the host grids leaf index set.
Definition: AdaptiveGrid.hpp:146
std::shared_ptr< HostGrid > const & hostGrid() const
Return the underlying grid.
Definition: AdaptiveGrid.hpp:68
bool adapt()
Adapt the grid and notify observers of the adapt event.
Definition: AdaptiveGrid.hpp:185
bool loadBalance(DataHandle &handle)
Calls loadBalance(handle) on the underlying grid.
Definition: AdaptiveGrid.hpp:267
bool isLevelwiseConforming(int level) const
Return true if the level-rid view represents a conforming grid.
Definition: AdaptiveGrid.hpp:293
int size(Dune::GeometryType type) const
Return number of leaf entities per geometry type in this process.
Definition: AdaptiveGrid.hpp:125
int size(int codim) const
Return number of leaf entities of a given codim in this process.
Definition: AdaptiveGrid.hpp:119
auto ilevelend(Element const &e) const
Obtain end intersection iterator with respect to the level GridView.
Definition: AdaptiveGrid.hpp:98
auto lend(int level) const
one past the end on this level
Definition: AdaptiveGrid.hpp:82
int getMark(Element const &e) const
Return refinement mark for entity.
Definition: AdaptiveGrid.hpp:171
Mixin for signaling of certain events.
Definition: Observer.hpp:57
Definition: AdaptiveGrid.hpp:344
Definition: Observer.hpp:25
Definition: Observer.hpp:30
Definition: Observer.hpp:19