KASKADE 7 development version
Loading...
Searching...
No Matches
gridmanager.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2023 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12#ifndef GRIDMANAGER_HH_
13#define GRIDMANAGER_HH_
14
15#include <ctime>
16#include <iostream>
17#include <mutex>
18#include <numeric>
19#include <utility>
20
21#include <boost/signals2.hpp>
22#include <boost/range/iterator_range.hpp>
23
24#include <dune/common/config.h>
25#include <dune/grid/common/capabilities.hh>
26#include <dune/grid/common/gridview.hh>
27#include <dune/grid/io/file/dgfparser/gridptr.hh>
28
29#include "fem/gridBasics.hh"
31#include "utilities/timing.hh"
32
33
34
35namespace Kaskade
36{
37
38 // forward declaration
39 template<class G, class T> class CellData;
40
41 // ----------------------------------------------------------------------------------------------
42
77
78 // ----------------------------------------------------------------------------------------------
79
89 template <class GridView>
91 {
92 public:
96 typedef typename GridView::template Codim<0>::Iterator CellIterator;
97
102 CellRanges() = default;
103
107 CellRanges(CellRanges&&) = default;
108
116 CellRanges(int nmax, GridView const& gridView): cellRanges(nmax+1)
117 {
118 // We know how many iterators we will insert - allocate space beforehand.
119 for (int n=1; n<=nmax; ++n)
120 cellRanges[n].reserve(n+1);
121
122 // number of cells
123 size_t const size = gridView.size(0);
124
125 // Step through all cells, storing the iterator in case it is at a boundary of cell ranges.
126 // The iteration through the cells is monotone, hence the ranges we construct cannot overlap.
127 // If few cells exist, some ranges may be empty, however.
128 // The following postconditions hold:
129 // (i) cellRanges[n].size() <= n.
130 // Proof: Assume cellRanges[n].size()==n. Then there is no cell with j >= size
131 // (it is at most size-1), where a further push_back could happen.
132 // (ii) cellRanges[n][0] == begin.
133 // Proof: In the first iterations j==0 and cellRanges[n].size()==0 holds,
134 // such that 0>=0 evaluates true and triggers the push_back(begin).
135 // (iii) any range contains less than size/n + 1 cells.
136 // Proof: Assume a range [r,s[. Then there is k with r>=k*size/n and t<(k+1)*size/n
137 // for all t<s. Thus s-1-r < ((k+1)-k)*size/n = size/n,
138 // such that the length is s-r < size/n + 1.
139 size_t j = 0; // cell counter
140 for (CellIterator i=gridView.template begin<0>(); i!=gridView.template end<0>(); ++i, ++j)
141 for (int n=1; n<=nmax; ++n)
142 if (j >= cellRanges[n].size()*size/n)
143 cellRanges[n].push_back(i);
144
145 // Now we have to make sure that every range vector contains the number of ranges
146 // it's supposed to hold. Add empty ranges as needed.
147 // As up to here the size of cellRanges[n] is at most n (not n+1), we automatically take care of
148 // terminating the last range with the end iterator.
149 for (int n=1; n<=nmax; ++n)
150 while (cellRanges[n].size()<n+1)
151 cellRanges[n].push_back(gridView.template end<0>());
152 }
153
158
164 boost::iterator_range<CellIterator> range(int n, int k) const
165 {
166 assert(1<=n && n<cellRanges.size());
167 assert(0<=k && k<n);
168 return boost::iterator_range<CellIterator>(cellRanges[n][k],cellRanges[n][k+1]);
169 }
170
175 int maxRanges() const
176 {
177 return static_cast<int>(cellRanges.size())-1;
178 }
179
180 private:
181 std::vector<std::vector<CellIterator>> cellRanges;
182 };
183
184 //----------------------------------------------------------------------------------------
185
186 // Start of implementation for better numbering of entities. Very much in progress, still.
187 template <class GridView>
189 {
190 using IndexSet = typename GridView::IndexSet;
191 constexpr static int dim = GridView::dimension;
192
193 public:
194 using Index = typename IndexSet::IndexType;
195
223
225 {
226 IndexSet const& is = gv.indexSet();
227 for (int codim=0; codim<=dim; ++codim)
228 indices[codim].resize(is.size(codim));
229
230 switch (order)
231 {
232 case SORTBYCODIM:
233 {
234 Index n = 0;
235 for (int codim=0; codim<=dim; ++codim)
236 {
237 std::iota(begin(indices[codim]),end(indices[codim]),n);
238 n += indices[codim].size();
239 }
240 break;
241 }
242 case SEQUENTIAL:
243 abort();
244 break;
245 case CUTHILLMCKEE:
246 abort();
247 break;
248 }
249 }
250
251 Index operator()(int codim, Index i) const
252 {
253 assert(0<=codim && codim<=dim);
254 assert(0<=i && i<indices[codim].size());
255 return indices[codim][i];
256 }
257
258 private:
259 std::array<std::vector<Index>,dim+1> indices;
260 };
261
262 //----------------------------------------------------------------------------------------
263
268 template<class Grd>
270 {
271 public:
275 using Grid = Grd;
276
278
279 GridManagerBase(Dune::GridPtr<Grid> grid_, bool verbose_, bool enforceConcurrentReads = false)
280 : GridManagerBase(grid_.release(),verbose_,enforceConcurrentReads)
281 {}
282
283 GridManagerBase(std::unique_ptr<Grid>&& grid_, bool verbose_, bool enforceConcurrentReads = false)
284 : GridManagerBase(grid_.release(),verbose_,enforceConcurrentReads)
285 {}
286
287 GridManagerBase(Grid*&& grid_, bool verbose_, bool enforceConcurrentReads = false):
288 markCount(0), gridptr(grid_),
289 gridIsThreadSafe_(Dune::Capabilities::viewThreadSafe<Grid>::v), enforceConcurrentReads_(enforceConcurrentReads),
290 levelRanges(gridptr->maxLevel()+1), verbose(verbose_)
291 {}
292
293 virtual ~GridManagerBase() {};
294
299
301 Grid const& grid() const
302 {
303 return *gridptr;
304 }
305
315 std::shared_ptr<Grid const> gridShared() const
316 {
317 return gridptr;
318 }
319
323
328
335 bool mark(int refCount, typename Grid::template Codim<0>::Entity const& cell)
336 {
337 if(refCount != 0)
338 {
339 ++markCount;
340 return gridptr->mark(refCount,cell);
341 }
342 return false;
343 }
344
346 template<class S>
347 void mark(CellData<Grid,S> const& cellData)
348 {
349 this->flushMarks();
351 typename CellData<Grid,S>::CellDataVector::const_iterator imark_end = cellData.end();
352 for(imark=cellData.begin(); imark != imark_end; ++imark)
353 {
354 auto ret = this->mark(imark->first,imark->second);
355 ++markCount;
356 if (!ret && imark->first!=0)
357 std::cout << "GRIDMANAGER: Warning: Cannot mark element!" << '\n';
358 }
359 }
360
364 size_t countMarked() const
365 {
366 return markCount;
367 }
368
370 bool preAdapt()
371 {
372 if (markCount > 0)
373 return gridptr->preAdapt();
374 else
375 return false;
376 };
377
380 {
381 gridptr->postAdapt();
382
383 if(verbose)
384 std::cout << "after refinement: " << gridptr->size(0) << " cells, "
385 << gridptr->size(Grid::dimension) << " vertices.\n";
386 };
387
388
395 {
396 this->preAdapt();
397 bool result = adapt();
398 #if !defined(NDEBUG)
399 if(!result)
400 std::cout << "GRIDMANAGER: Nothing has been refined!" << '\n';
401 #endif
402 this->postAdapt();
403 return result;
404 }
405
408 {
409 for (auto const& element: elements(gridptr->leafGridView()))
410 mark(0,element);
411
412 markCount = 0;
413 }
414
419 bool adapt()
420 {
421 bool result;
422 if (this->markCount > 0)
423 {
424 Timings& timer = Timings::instance();
425 ScopedTimingSection refineSection("grid refinement");
426
427 timer.start("before refinement");
428 this->beforeRefinement();
429 timer.stop("before refinement");
430
431 if (verbose)
432 std::cout << "\nGRIDMANAGER: mesh is refined from " << this->gridptr->size(0) << " cells " << std::flush;
433
434 timer.start("adapt");
435 result = adaptGrid();
436 update();
437 timer.stop("adapt");
438
439 if(verbose)
440 std::cout << "to " << this->gridptr->size(0) << " cells" << '\n';
441
442 timer.start("after refinement");
443 this->afterRefinement();
444 timer.stop("after refinement");
445
446 this->markCount = 0;
447 }
448 else
449 result = false;
450 return result;
451 }
452
457 void globalRefine(int refCount)
458 {
459 if (refCount<=0)
460 return;
461
462 Timings& timer = Timings::instance();
463 ScopedTimingSection refineSection("grid refinement");
464 timer.start("before refinement");
465 this->beforeRefinement();
466 timer.stop("before refinement");
467
468 timer.start("adapt");
469 refineGrid(refCount);
470 update();
471 timer.stop("adapt");
472
473 timer.start("after refinement");
474 this->afterRefinement();
475 timer.stop("after refinement");
476
477 this->markCount = 0;
478 };
479
483 virtual void update() = 0;
484
488
493 {
494 enforceConcurrentReads_ = enforceConcurrentReads;
495 return *this;
496 }
497
498
507 Self& setVerbosity(const bool verbosity)
508 {
509 verbose = verbosity; return *this;
510 }
511
524 bool gridIsThreadSafe() const
525 {
526#ifdef NDEBUG
527 return gridIsThreadSafe_ || enforceConcurrentReads_;
528#else
529 return false;
530#endif
531 }
532
533
541 CellRanges<typename Grid::LeafGridView> const& cellRanges(typename Grid::LeafGridView const&) const
542 {
543 std::lock_guard<std::mutex> lock(cellRangeMutex);
544 if (!leafRanges)
545 leafRanges.reset(new CellRanges<typename Grid::LeafGridView>(2*NumaThreadPool::instance().cpus(),grid().leafGridView()));
546
547 return *leafRanges;
548 }
549
557 CellRanges<typename Grid::LevelGridView> const& cellRanges(typename Grid::LevelGridView const& gridView) const
558 {
559 int const level = gridView.template begin<0>()->level(); // cells have the level of their level view (inferred from the Dune tutorial)
560 assert(level<=grid().maxLevel());
561
562 std::lock_guard<std::mutex> lock(cellRangeMutex);
563 if (levelRanges[level].maxRanges()<0)
564 levelRanges[level] = CellRanges<typename Grid::LevelGridView>(2*NumaThreadPool::instance().cpus(),grid().levelGridView(level));
565 // we could have used gridView directly here. But can we make sure this is a level view of the grid we keep?
566 return levelRanges[level];
567 }
568
573 EntityNumbering<typename Grid::LeafGridView> const& entityNumbering(typename Grid::LeafGridView const&) const
574 {
576
577 std::lock_guard<std::mutex> lock(cellRangeMutex); // maybe we should use our own mutex here?
578 if (!leafEntityNumbers)
579 leafEntityNumbers = std::make_unique<Numbering>(grid().leafGridView(),Numbering::SORTBYCODIM);
580
581 return *leafEntityNumbers;
582 }
583
584
585 private:
586 // TODO: docme!
587 virtual void refineGrid(int refcount) = 0;
588 virtual bool adaptGrid() = 0;
589
590 size_t markCount; // number of cells marked for refinement/coarsening
591
592 protected:
594 {
595 // trigger creation of transfer data structures
596 signals.informAboutRefinement(GridSignals::BeforeRefinement);
597 signals.informAboutRefinement(GridSignals::BeforeRefinementComplete);
598
599 // invalidate the cell range data structures
600 leafRanges.reset();
601 levelRanges.clear();
602 leafEntityNumbers.reset();
603 }
604
606 {
607 levelRanges.resize(grid().maxLevel()+1);
608 signals.informAboutRefinement(GridSignals::AfterRefinement);
609 signals.informAboutRefinement(GridSignals::TransferCompleted);
610 }
611
612 template<class LocalToGlobalMapper> friend class FEFunctionSpace;
613 template<class GridMan, class ErrEst> friend class AdaptiveGrid;
614
618 std::shared_ptr<Grid> gridptr;
619
620 public:
622
623 private:
624 const bool gridIsThreadSafe_;
625
627 bool enforceConcurrentReads_;
628
629 // cell ranges and entity numberings are constructed on demand
630 mutable std::mutex cellRangeMutex;
631 mutable std::unique_ptr<CellRanges<typename Grid::LeafGridView>> leafRanges;
632 mutable std::vector<CellRanges<typename Grid::LevelGridView>> levelRanges;
633 mutable std::unique_ptr<EntityNumbering<typename Grid::LeafGridView>> leafEntityNumbers;
634
635 protected:
637 };
638
639 // -------------------------------------------------------------------
640
689 template <class Grd>
690 class GridManager : public GridManagerBase<Grd>
691 {
692 public:
693 typedef Grd Grid;
694
702 explicit GridManager(Dune::GridPtr<Grid> grid_, bool verbose=false)
704 {}
705
707
711 explicit GridManager(std::unique_ptr<Grid>&& grid_, bool verbose=false)
712 : GridManagerBase<Grid>( std::move(grid_),verbose)
713 {}
714
716
720 explicit GridManager(Grid*&& grid_, bool verbose=false)
721 : GridManagerBase<Grid>( std::move(grid_),verbose)
722 {}
723
724
725 virtual void update() {}
726
727 private:
728 virtual void refineGrid(int refCount)
729 {
730 this->gridptr->globalRefine(refCount);
731 };
732
733
734 virtual bool adaptGrid()
735 {
736 return this->gridptr->adapt();
737 };
738 };
739
740
741 //---------------------------------------------------------------------
742
749 template <class Grid>
751 {
752 for (auto const& cell: elements(gridManager.grid().leafGridView()))
753 if (cell.hasBoundaryIntersections())
754 gridManager.mark(1,cell);
755 gridManager.adaptAtOnce();
756 }
757}
758
759#endif /* GRIDMANAGER_HH_ */
Class that stores information for each cell of a grid.
Definition celldata.hh:37
CellDataVector::const_iterator end() const
Return a const_iterator on data.end()
Definition celldata.hh:159
CellDataVector::const_iterator begin() const
Return a const_iterator on data.begin()
Definition celldata.hh:156
A class storing cell ranges of roughly equal size for multithreaded mesh traversal.
GridView::template Codim< 0 >::Iterator CellIterator
The type of iterator to step through the cells of the given view.
int maxRanges() const
Obtain the maximum number of ranges. Default constructed "empty" cell ranges return a negative value.
CellRanges< GridView > & operator=(CellRanges< GridView > &&)=default
Move assignment.
boost::iterator_range< CellIterator > range(int n, int k) const
Obtain cell range.
CellRanges(CellRanges &&)=default
Move constructor.
CellRanges()=default
Default constructor. This creates a pretty useless empty cell ranges object.
CellRanges(int nmax, GridView const &gridView)
Constructs cell ranges.
EntityNumbering(GridView const &gv, SortOrder order)
SortOrder
Defines the available orderings.
@ CUTHILLMCKEE
sorts all entities according to their adjacency by Cuthill-McKee This provides small bandwidth of sti...
@ SEQUENTIAL
sorts cells according to the cell iterator of the grid view, and places lower codim entities close to...
@ SORTBYCODIM
sorts cells first, then faces, edges, and vertices last
typename IndexSet::IndexType Index
Index operator()(int codim, Index i) const
Basic functionality for managing grids and their refinement.
GridManagerBase(Dune::GridPtr< Grid > grid_, bool verbose_, bool enforceConcurrentReads=false)
void globalRefine(int refCount)
Refines each leaf cell of the grid and prolongates registered FE functions to the new leaf grid view.
size_t countMarked() const
Reports the number of marked elements.
virtual void update()=0
Must be overloaded by derived classes to adjust internal state immediately after mesh refinement.
bool preAdapt()
Calls grid.preAdapt().
bool adapt()
Refines each marked leaf cell of the grid and prolongates registered FE functions to the new leaf gri...
CellRanges< typename Grid::LeafGridView > const & cellRanges(typename Grid::LeafGridView const &) const
Returns a CellRanges object for the given grid view. The cell ranges are created on demand,...
Grid const & grid() const
Returns a const reference on the owned grid.
bool adaptAtOnce()
Performs grid refinement.
void mark(CellData< Grid, S > const &cellData)
Marks all Entities of a grid according to the corresponding entries in a CellData.
bool gridIsThreadSafe() const
Returns true if concurrent read accesses to the grid do not lead to data races.
void postAdapt()
Calls grid.postAdapt().
EntityNumbering< typename Grid::LeafGridView > const & entityNumbering(typename Grid::LeafGridView const &) const
Returns an EntityNumbering object for the given grid view.
void flushMarks()
Remove all cell marks from the grid.
GridManagerBase(std::unique_ptr< Grid > &&grid_, bool verbose_, bool enforceConcurrentReads=false)
std::shared_ptr< Grid const > gridShared() const
Provides a read-only shared pointer to the underlying grid.
CellRanges< typename Grid::LevelGridView > const & cellRanges(typename Grid::LevelGridView const &gridView) const
Returns a CellRanges object for the given grid view.
bool mark(int refCount, typename Grid::template Codim< 0 >::Entity const &cell)
Marks the given cell for refinement or coarsening.
GridManagerBase(Grid *&&grid_, bool verbose_, bool enforceConcurrentReads=false)
Self & enforceConcurrentReads(bool enforceConcurrentReads)
Self & setVerbosity(const bool verbosity)
sets the verbosity level of the grid manager
GridManager(std::unique_ptr< Grid > &&grid_, bool verbose=false)
Construction from a unique_ptr<Grid>
virtual void update()
Must be overloaded by derived classes to adjust internal state immediately after mesh refinement.
GridManager(Dune::GridPtr< Grid > grid_, bool verbose=false)
Construction from a GridPtr<Grid>
GridManager(Grid *&&grid_, bool verbose=false)
Construction from a Grid*.
static NumaThreadPool & instance(int maxThreads=std::numeric_limits< int >::max())
Returns a globally unique thread pool instance.
A scope guard object that automatically closes a timing section on destruction.
Definition timing.hh:181
Supports gathering and reporting execution times information for nested program parts.
Definition timing.hh:64
static Timings & instance()
Returns a reference to a single default instance.
void stop(std::string const &name)
Stops the timing of given section.
struct Times const * start(std::string const &name)
Starts or continues the timing of given section.
boost::signals2::signal< void(Status)> informAboutRefinement
A signal that is emitted thrice on grid modifications, once before adaptation takes place and twice a...
void refineAtBoundary(GridManagerBase< Grid > &gridManager)
A convenience routine that refines all cells incident to a boundary face.
Status
The argument type of the signal that is emitted before and after grid adaptation.
int const LagrangeCubeShapeFunction< ctype, dimension, Scalar, O >::order
A class that provides access to signals that are emitted from the grid manager on various occasions.