From ee65b18e3d92c9b96ad537d98c41da11fcebdc50 Mon Sep 17 00:00:00 2001 From: "Praetorius, Simon" <simon.praetorius@tu-dresden.de> Date: Fri, 19 Oct 2018 18:46:05 +0200 Subject: [PATCH] GridFunctionMarker --- examples/init/marker.dat.2d | 4 + src/amdis/Marker.hpp | 326 ++++++++++++++++--------- src/amdis/Marker.inc.hpp | 229 +++++++++++------ src/amdis/ProblemStat.hpp | 22 +- src/amdis/ProblemStat.inc.hpp | 19 +- src/amdis/ProblemStatBase.hpp | 5 +- src/amdis/StandardProblemIteration.cpp | 4 +- test/CMakeLists.txt | 4 + test/MarkerTest.cpp | 59 +++++ 9 files changed, 468 insertions(+), 204 deletions(-) create mode 100644 examples/init/marker.dat.2d create mode 100644 test/MarkerTest.cpp diff --git a/examples/init/marker.dat.2d b/examples/init/marker.dat.2d new file mode 100644 index 00000000..7ca1df7e --- /dev/null +++ b/examples/init/marker.dat.2d @@ -0,0 +1,4 @@ +dimension of world: 2 + +test->mesh: testMesh +testMesh->global refinements: 0 diff --git a/src/amdis/Marker.hpp b/src/amdis/Marker.hpp index ba2fa1fd..2941248b 100644 --- a/src/amdis/Marker.hpp +++ b/src/amdis/Marker.hpp @@ -1,155 +1,118 @@ #pragma once +#include <limits> #include <string> +#include <utility> +#include <dune/common/std/optional.hh> #include <dune/grid/common/grid.hh> +#include <amdis/common/ConceptsBase.hpp> + +#include <amdis/gridfunctions/GridFunctionConcepts.hpp> + #include <amdis/AdaptInfo.hpp> #include <amdis/Flag.hpp> #include <amdis/Initfile.hpp> -namespace AMDiS { - - +namespace AMDiS +{ /** * \ingroup Adaption * * \brief - * Base class for all scalar markers. + * Base class for all markers. */ - template <class Traits> + template <class Grid> class Marker { protected: - using GlobalBasis = typename Traits::GlobalBasis; - using GridView = typename GlobalBasis::GridView; - using Grid = typename GridView::Grid; - using IndexSet = typename GridView::IndexSet; + using GridView = typename Grid::LeafGridView; using Element = typename GridView::template Codim<0>::Entity; - using Estimates = std::vector<double>; public: /// Constructor. - Marker() {} + Marker() = default; /// Constructor. - Marker(std::string const& name, std::string const& component, Estimates const& est, - std::shared_ptr<Grid> const& grid) + Marker(std::string const& name, std::shared_ptr<Grid> const& grid) : name_(name) - , component_(component) , grid_(grid) - , est_(est) - , maximumMarking_(false) { - Parameters::get(name + "->p", p_); Parameters::get(name + "->info", info_); Parameters::get(name + "->max refinement level", maxRefineLevel_); Parameters::get(name + "->min refinement level", minRefineLevel_); } - /// destructor - virtual ~Marker() {} + /// Destructor. + virtual ~Marker() = default; /// Marks element with newMark. If \ref maximumMarking_ is set, the element /// is marked only if the new mark is bigger than the old one. The return /// value specifies whether the element has been marked, or not. - void mark(Element const& elem, int newMark) - { - int oldMark = grid_->getMark(elem); - - if (!maximumMarking_ || (newMark > oldMark)) { - bool marked = grid_->mark(newMark, elem); - if (marked) { - if (oldMark > 0) { - elMarkRefine_--; - } else if (oldMark < 0) { - elMarkCoarsen_--; - } - - if (newMark > 0) { - elMarkRefine_++; - } else if (newMark < 0) { - elMarkCoarsen_++; - } - } else { - msg("Marking failed"); - } - } - } + void mark(Element const& elem, int newMark); - /// Can be used by sub classes. Called before traversal. + /// Called before traversal. virtual void initMarking(AdaptInfo& adaptInfo); - /// Can be used by sub classes. Called after traversal. + /// Called after traversal. virtual void finishMarking(AdaptInfo& adaptInfo); /// Marks one element. - virtual void markElement(AdaptInfo& adaptInfo, Element const& elem); + virtual void markElement(AdaptInfo& adaptInfo, Element const& elem) = 0; - /// Marking of the mesh. + /// Marking of the whole grid. virtual Flag markGrid(AdaptInfo& adaptInfo); - /// Sets \ref maximumMarking. - void setMaximumMarking(bool maxMark) - { - maximumMarking_ = maxMark; - } - - int getElMarkRefine() + /// Returns \ref elMarkRefine_ of the Marker + int getElMarkRefine() const { return elMarkRefine_; } - int getElMarkCoarsen() + /// Returns \ref elMarkCoarsen_ of the Marker + int getElMarkCoarsen() const { return elMarkCoarsen_; } - /// Returns \ref name of the Marker - std::string const& getName() const + /// Returns \ref name_ of the Marker + std::string getName() const { return name_; } - /// Creates a scalar marker depending on the strategy set in parameters. - static std::unique_ptr<Marker<Traits> > createMarker(std::string const& name, std::string const& component, Estimates const& est, std::shared_ptr<Grid> const& grid); + /// Sets \ref maximumMarking_. + void setMaximumMarking(bool maxMark) + { + maximumMarking_ = maxMark; + } + + /// Sets \ref refineAllowed_. + void allowRefinement(bool allow) + { + refineAllowed_ = allow; + } + + /// Sets \ref coarsenAllowed_. + void allowCoarsening(bool allow) + { + coarsenAllowed_ = allow; + } protected: - /// Name of the scalar marker. + /// Name of the marker. std::string name_; - /// Problem component to work on - std::string component_; - /// Pointer to the grid std::shared_ptr<Grid> grid_; - /// Pointer to the local error estimates - Estimates est_; - - /// estimation sum - double estSum_ = 0.0; - - /// estmation maximum - double estMax_ = 0.0; - /// If true, elements are marked only if the new value is bigger than /// the current marking. - bool maximumMarking_; - - /// Lower limit for error estimation, from which an element is marked for - /// refinement - double markRLimit_; - - /// Upper limit for error estimation, from which an element is marked for - /// coarsening - double markCLimit_; - - /// power in estimator norm TODO: is this info necessary in marker? - double p_ = 2.0; + bool maximumMarking_ = false; /// Info level. - int info_ = 10; + int info_ = 0; /// Counter for elements marked for refinement int elMarkRefine_ = 0; @@ -163,9 +126,76 @@ namespace AMDiS { /// Minimal level of all elements. int minRefineLevel_ = -1; + /// Allow elements to be marked for refinement bool refineAllowed_ = true; - bool coarsenAllowed_ = false; + /// Allow elements to be marked for coarsening + bool coarsenAllowed_ = true; + }; + + + /** + * \ingroup Adaption + * + * \brief + * Base class for all estimator-based markers. + */ + template <class Grid> + class EstimatorMarker + : public Marker<Grid> + { + protected: + using Super = Marker<Grid>; + using Element = typename Super::Element; + using Estimates = std::vector<double>; + + public: + /// Constructor. + EstimatorMarker() = default; + + /// Constructor. + EstimatorMarker(std::string name, std::string component, Estimates const& est, + std::shared_ptr<Grid> const& grid) + : Super{std::move(name), grid} + , component_(std::move(component)) + , est_(est) + { + Parameters::get(this->name_ + "->p", p_); + } + + /// Can be used by sub classes. Called before traversal. + virtual void initMarking(AdaptInfo& adaptInfo) override; + + /// Marks one element. + virtual void markElement(AdaptInfo& adaptInfo, Element const& elem) override; + + /// Creates a scalar marker depending on the strategy set in parameters. + static std::unique_ptr<EstimatorMarker<Grid> > createMarker(std::string const& name, + std::string const& component, Estimates const& est, std::shared_ptr<Grid> const& grid); + + protected: + /// Problem component to work on + std::string component_; + + /// Pointer to the local error estimates + Estimates est_; + + /// Estimation sum + double estSum_ = 0.0; + + /// Estmation maximum + double estMax_ = 0.0; + + /// Lower limit for error estimation, from which an element is marked for + /// refinement + double markRLimit_; + + /// Upper limit for error estimation, from which an element is marked for + /// coarsening + double markCLimit_; + + /// Power in estimator norm + double p_ = 2.0; }; @@ -175,24 +205,22 @@ namespace AMDiS { * \brief * Global refinement. */ - template <class Traits> + template <class Grid> class GRMarker - : public Marker<Traits> + : public EstimatorMarker<Grid> { - using Super = Marker<Traits>; - using Grid = typename Super::Grid; + using Super = EstimatorMarker<Grid>; using Element = typename Super::Element; using Estimates = typename Super::Estimates; public: /// Constructor. - GRMarker(std::string const& name, std::string component, Estimates const& est, + GRMarker(std::string const& name, std::string const& component, Estimates const& est, std::shared_ptr<Grid> const& grid) - : Marker<Traits>(name, std::move(component), est, grid) + : Super{name, component, est, grid} {} - /// Implementation of Marker::markElement(). - virtual void markElement(AdaptInfo& adaptInfo, Element const& elem) + virtual void markElement(AdaptInfo& adaptInfo, Element const& elem) override { if (this->refineAllowed_) this->mark(elem, 1); @@ -207,12 +235,11 @@ namespace AMDiS { * Maximum strategy. */ - template <class Traits> + template <class Grid> class MSMarker - : public Marker<Traits> + : public EstimatorMarker<Grid> { - using Super = Marker<Traits>; - using Grid = typename Super::Grid; + using Super = EstimatorMarker<Grid>; using Estimates = typename Super::Estimates; public: @@ -225,8 +252,7 @@ namespace AMDiS { Parameters::get(name + "->MSGammaC", msGammaC_); } - /// Implementation of Marker::initMarking(). - void initMarking(AdaptInfo& adaptInfo); + virtual void initMarking(AdaptInfo& adaptInfo) override; protected: /// Marking parameter. @@ -244,12 +270,11 @@ namespace AMDiS { * Equidistribution strategy */ - template <class Traits> + template <class Grid> class ESMarker - : public Marker<Traits> + : public EstimatorMarker<Grid> { - using Super = Marker<Traits>; - using Grid = typename Super::Grid; + using Super = EstimatorMarker<Grid>; using Estimates = typename Super::Estimates; public: @@ -262,8 +287,7 @@ namespace AMDiS { Parameters::get(name + "->ESThetaC", esThetaC_); } - /// Implementation of Marker::initMarking(). - virtual void initMarking(AdaptInfo& adaptInfo); + virtual void initMarking(AdaptInfo& adaptInfo) override; protected: /// Marking parameter. @@ -281,12 +305,11 @@ namespace AMDiS { * Guaranteed error reduction strategy */ - template <class Traits> + template <class Grid> class GERSMarker - : public Marker<Traits> + : public EstimatorMarker<Grid> { - using Super = Marker<Traits>; - using Grid = typename Super::Grid; + using Super = EstimatorMarker<Grid>; using Element = typename Super::Element; using Estimates = typename Super::Estimates; @@ -301,8 +324,7 @@ namespace AMDiS { Parameters::get(name + "->GERSThetaC", gersThetaC_); } - /// Implementation of Marker::markGrid(). - virtual Flag markGrid(AdaptInfo& adaptInfo); + virtual Flag markGrid(AdaptInfo& adaptInfo) override; protected: /// Refinement marking function. @@ -328,6 +350,86 @@ namespace AMDiS { double gersThetaC_ = 0.1; }; -} + + /** + * \ingroup Adaption + * + * \brief + * Marker based on an indicator given as grid-function. + * + * On each element the grid-function is evaluated in the barycenter. The returned + * values must be an integer (or convertible to an integer) indicating the + * desired refinement level of this element. The element is marked for refinement + * if the current level is < the desired level or coarsened, if >. + * + * \tparam Grid An Implementation of the \ref Dune::Grid interface + * \tparam GridFct A grid-function with `Range` convertible to `int` + */ + template <class Grid, class GridFct> + class GridFunctionMarker + : public Marker<Grid> + { + using Super = Marker<Grid>; + using Element = typename Super::Element; + + template <class GF> + using IsGridFunction = decltype(localFunction(std::declval<GF>())); + + static_assert(Dune::Std::is_detected<IsGridFunction,GridFct>::value, ""); + + public: + /// Constructor. + template <class GF> + GridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid, GF&& gf, + Dune::Std::optional<int> maxRef = { /*max*/ }, + Dune::Std::optional<int> minRef = { /*0*/ }) + : Super{name, grid} + , gridFct_{makeGridFunction(std::forward<GF>(gf), grid->leafGridView())} + { + + this->maxRefineLevel_ = maxRef ? maxRef.value() : + (this->maxRefineLevel_ == -1 ? std::numeric_limits<int>::max() : this->maxRefineLevel_); + this->minRefineLevel_ = minRef ? minRef.value() : + (this->minRefineLevel_ == -1 ? 0 : this->minRefineLevel_); + } + + /// \brief Implementation of \ref Marker::markElement. Does nothing since marking is + /// done in \ref markGrid(). + virtual void markElement(AdaptInfo& adaptInfo, Element const& elem) final {} + + /// Mark element for refinement, if grid-function \ref gridFct_ evaluates to + /// a value larger than the current level and is marked for coarsening of + /// the result is less than the current value. + virtual Flag markGrid(AdaptInfo& adaptInfo) override; + + private: + /// Indicator function for adaptation + GridFct gridFct_; + }; + +#if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION + // Deduction guide for GridFunctionMarker class + template <class Grid, class PreGridFct> + GridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid, + PreGridFct&& preGridFct, + Dune::Std::optional<int> maxRef = {}, + Dune::Std::optional<int> minRef = {}) + -> GridFunctionMarker<Grid, + std::decay_t<decltype(makeGridFunction(std::forward<PreGridFct>(preGridFct), grid->leafGridView()))>>; +#endif + + // Generator function for GridFunctionMarker class + template <class Grid, class PreGridFct> + auto makeGridFunctionMarker(std::string const& name, std::shared_ptr<Grid> const& grid, + PreGridFct&& preGridFct, + Dune::Std::optional<int> maxRef = { /*max*/ }, + Dune::Std::optional<int> minRef = { /*0*/ }) + { + auto gridFct = makeGridFunction(std::forward<PreGridFct>(preGridFct), grid->leafGridView()); + using GridFct = decltype(gridFct); + return GridFunctionMarker<Grid,GridFct>{name, grid, gridFct, maxRef, minRef}; + } + +} // end namespace AMDiS #include "Marker.inc.hpp" diff --git a/src/amdis/Marker.inc.hpp b/src/amdis/Marker.inc.hpp index e9f08a9a..9bd74e68 100644 --- a/src/amdis/Marker.inc.hpp +++ b/src/amdis/Marker.inc.hpp @@ -2,105 +2,134 @@ namespace AMDiS { -template <class Traits> -std::unique_ptr<Marker<Traits> > Marker<Traits>:: -createMarker(std::string const& name, std::string const& component, - Estimates const& est, std::shared_ptr<Grid> const& grid) +template <class Grid> +void Marker<Grid>::mark(Element const& elem, int newMark) { - int strategy = 0; - Parameters::get(name + "->strategy", strategy); - - switch (strategy) { - case 0: // no refinement/coarsening - break; - case 1: - msg("Creating global refinement (GR) marker"); - return std::make_unique<GRMarker<Traits> >(name, component, est, grid); - break; - case 2: - msg("Creating maximum strategy (MS) marker"); - return std::make_unique<MSMarker<Traits> >(name, component, est, grid); - break; - case 3: - msg("Creating equidistribution strategy (ES) marker"); - return std::make_unique<ESMarker<Traits> >(name, component, est, grid); - break; - case 4: - msg("Creating guaranteed error reduction strategy (GERS) marker"); - return std::make_unique<GERSMarker<Traits> >(name, component, est, grid); - break; - default: - error_exit("invalid strategy"); + int oldMark = grid_->getMark(elem); + + if (!maximumMarking_ || (newMark > oldMark)) { + bool marked = grid_->mark(newMark, elem); + if (marked) { + if (oldMark > 0) { + elMarkRefine_--; + } else if (oldMark < 0) { + elMarkCoarsen_--; + } + + if (newMark > 0) { + elMarkRefine_++; + } else if (newMark < 0) { + elMarkCoarsen_++; + } + } else { + msg("Marking failed"); + } } - - return {}; -} - - -template <class Traits> -void Marker<Traits>::initMarking(AdaptInfo& adaptInfo) -{ - elMarkRefine_ = 0; - elMarkCoarsen_ = 0; - estSum_ = std::pow(adaptInfo.getEstSum(component_), p_); - estMax_ = adaptInfo.getEstMax(component_); - refineAllowed_ = adaptInfo.isRefinementAllowed(component_); - coarsenAllowed_ = adaptInfo.isCoarseningAllowed(component_); } -template <class Traits> -void Marker<Traits>::finishMarking(AdaptInfo& adaptInfo) +template <class Grid> +void Marker<Grid>::initMarking(AdaptInfo& adaptInfo) { - msg("{} elements marked for refinement", elMarkRefine_); - msg("{} elements marked for coarsening", elMarkCoarsen_); + this->elMarkRefine_ = 0; + this->elMarkCoarsen_ = 0; } -template <class Traits> -void Marker<Traits>::markElement(AdaptInfo& adaptInfo, const Element& elem) +template <class Grid> +void Marker<Grid>::finishMarking(AdaptInfo& adaptInfo) { - const auto& index = grid_->leafIndexSet().index(elem); - double lError = est_[index]; - - if (lError > markRLimit_ && refineAllowed_ - && (maxRefineLevel_ == -1 || elem.level() < maxRefineLevel_)) { - this->mark(elem, 1); - } else if (lError <= markCLimit_ && coarsenAllowed_ - && (minRefineLevel_ == -1 || elem.level() > minRefineLevel_)) { - this->mark(elem, -1); + if (info_ > 0) { + msg("{} elements marked for refinement", elMarkRefine_); + msg("{} elements marked for coarsening", elMarkCoarsen_); } } -template <class Traits> -Flag Marker<Traits>::markGrid(AdaptInfo& adaptInfo) +template <class Grid> +Flag Marker<Grid>::markGrid(AdaptInfo& adaptInfo) { - if (!grid_) - error_exit("No grid!"); + test_exit(bool(this->grid_), "No grid!"); initMarking(adaptInfo); - if (!coarsenAllowed_ && !refineAllowed_) + if (!this->coarsenAllowed_ && !this->refineAllowed_) return 0; - for (const auto& elem : Dune::elements(grid_->leafGridView())) + for (const auto& elem : Dune::elements(this->grid_->leafGridView())) markElement(adaptInfo, elem); finishMarking(adaptInfo); Flag markFlag; - if (elMarkRefine_) + if (this->elMarkRefine_) markFlag = 1; - if (elMarkCoarsen_) + if (this->elMarkCoarsen_) markFlag |= 2; return markFlag; } +template <class Grid> +void EstimatorMarker<Grid>::initMarking(AdaptInfo& adaptInfo) +{ + Super::initMarking(adaptInfo); + estSum_ = std::pow(adaptInfo.getEstSum(component_), p_); + estMax_ = adaptInfo.getEstMax(component_); + this->refineAllowed_ = adaptInfo.isRefinementAllowed(component_); + this->coarsenAllowed_ = adaptInfo.isCoarseningAllowed(component_); +} + -template <class Traits> -void MSMarker<Traits>::initMarking(AdaptInfo& adaptInfo) +template <class Grid> +void EstimatorMarker<Grid>::markElement(AdaptInfo& adaptInfo, const Element& elem) +{ + const auto& index = this->grid_->leafIndexSet().index(elem); + double lError = est_[index]; + + if (lError > markRLimit_ && this->refineAllowed_ + && (this->maxRefineLevel_ == -1 || elem.level() < this->maxRefineLevel_)) { + this->mark(elem, 1); + } else if (lError <= markCLimit_ && this->coarsenAllowed_ + && (this->minRefineLevel_ == -1 || elem.level() > this->minRefineLevel_)) { + this->mark(elem, -1); + } +} + + +template <class Grid> +std::unique_ptr<EstimatorMarker<Grid>> EstimatorMarker<Grid>:: +createMarker(std::string const& name, std::string const& component, + Estimates const& est, std::shared_ptr<Grid> const& grid) +{ + int strategy = 0; + Parameters::get(name + "->strategy", strategy); + + switch (strategy) { + case 0: // no refinement/coarsening + break; + case 1: + return std::make_unique<GRMarker<Grid> >(name, component, est, grid); + break; + case 2: + return std::make_unique<MSMarker<Grid> >(name, component, est, grid); + break; + case 3: + return std::make_unique<ESMarker<Grid> >(name, component, est, grid); + break; + case 4: + return std::make_unique<GERSMarker<Grid> >(name, component, est, grid); + break; + default: + error_exit("invalid strategy"); + } + + return {}; +} + + +template <class Grid> +void MSMarker<Grid>::initMarking(AdaptInfo& adaptInfo) { Super::initMarking(adaptInfo); @@ -115,8 +144,8 @@ void MSMarker<Traits>::initMarking(AdaptInfo& adaptInfo) } -template <class Traits> -void ESMarker<Traits>::initMarking(AdaptInfo& adaptInfo) +template <class Grid> +void ESMarker<Grid>::initMarking(AdaptInfo& adaptInfo) { Super::initMarking(adaptInfo); @@ -125,9 +154,9 @@ void ESMarker<Traits>::initMarking(AdaptInfo& adaptInfo) double epsP = std::pow(adaptInfo.getSpaceTolerance(this->component_), this->p_); int nLeaves = (this->grid_->leafGridView()).size(0); -/*#ifdef HAVE_PARALLEL_DOMAIN_AMDIS - Parallel::mpi::globalAdd(nLeaves); -#endif*/ +#if AMDIS_HAS_PARALLEL + Dune::CollectiveCommunication<>{}.sum(nLeaves, 1); +#endif this->markRLimit_ = esThetaP * epsP / nLeaves; this->markCLimit_ = esThetaCP * epsP / nLeaves; @@ -136,8 +165,8 @@ void ESMarker<Traits>::initMarking(AdaptInfo& adaptInfo) } -template <class Traits> -Flag GERSMarker<Traits>::markGrid(AdaptInfo& adaptInfo) +template <class Grid> +Flag GERSMarker<Grid>::markGrid(AdaptInfo& adaptInfo) { Super::initMarking(adaptInfo); @@ -210,8 +239,8 @@ Flag GERSMarker<Traits>::markGrid(AdaptInfo& adaptInfo) } -template <class Traits> -void GERSMarker<Traits>::markElementForRefinement(AdaptInfo& adaptInfo, const Element& elem) +template <class Grid> +void GERSMarker<Grid>::markElementForRefinement(AdaptInfo& adaptInfo, const Element& elem) { double lError = this->est_[this->grid_->leafIndexSet().index(elem)]; @@ -222,8 +251,8 @@ void GERSMarker<Traits>::markElementForRefinement(AdaptInfo& adaptInfo, const El } -template <class Traits> -void GERSMarker<Traits>::markElementForCoarsening(AdaptInfo& adaptInfo, const Element& elem) +template <class Grid> +void GERSMarker<Grid>::markElementForCoarsening(AdaptInfo& adaptInfo, const Element& elem) { double lError = this->est_[this->grid_->leafIndexSet().index(elem)]; @@ -238,4 +267,48 @@ void GERSMarker<Traits>::markElementForCoarsening(AdaptInfo& adaptInfo, const El } +template <class Grid, class PreGridFct> +Flag GridFunctionMarker<Grid, PreGridFct>::markGrid(AdaptInfo& adaptInfo) +{ + test_exit(bool(this->grid_), "No grid!"); + + Super::initMarking(adaptInfo); + + if (!this->coarsenAllowed_ && !this->refineAllowed_) + return 0; + + auto localFct = localFunction(gridFct_); + + for (auto const& e : Dune::elements(this->grid_->leafGridView())) { + localFct.bind(e); + int currentLevel = e.level(); + auto geo = e.geometry(); + auto const& ref = Dune::referenceElement(geo); + int targetLevel = 0; + int codim = ref.dimension; + + for (int i = 0; i < ref.size(codim); i++) + targetLevel = std::max(targetLevel, (int)std::round(localFct(ref.position(i, codim)))); + + int m = ((((targetLevel > currentLevel) && (currentLevel < this->maxRefineLevel_)) + || (currentLevel < this->minRefineLevel_)) + && this->refineAllowed_) + - ((((targetLevel < currentLevel) && (currentLevel > this->minRefineLevel_)) + || (currentLevel > this->maxRefineLevel_)) + && this->coarsenAllowed_); + this->mark(e, m); + localFct.unbind(); + } + + Super::finishMarking(adaptInfo); + + Flag markFlag; + if (this->elMarkRefine_) + markFlag = 1; + if (this->elMarkCoarsen_) + markFlag |= 2; + + return markFlag; +} + } // end namespace AMDiS diff --git a/src/amdis/ProblemStat.hpp b/src/amdis/ProblemStat.hpp index 8509e68b..74eb5c10 100644 --- a/src/amdis/ProblemStat.hpp +++ b/src/amdis/ProblemStat.hpp @@ -16,6 +16,7 @@ #include <amdis/CreatorInterface.hpp> #include <amdis/CreatorMap.hpp> #include <amdis/DirichletBC.hpp> +//#include <amdis/Estimator.hpp> #include <amdis/Flag.hpp> #include <amdis/Initfile.hpp> #include <amdis/LinearAlgebra.hpp> @@ -216,16 +217,28 @@ namespace AMDiS Grid const& grid() const { return *grid_; } /// Set the grid. Stores pointer and initializes feSpaces - /// matrices and vectors, as well as the file-writer. + /// matrices and vectors, as well as markers and file-writers. void setGrid(std::shared_ptr<Grid> const& grid) { grid_ = grid; - createGlobalBasis(); createMatricesAndVectors(); + createMarker(); createFileWriter(); } + void addMarker(std::shared_ptr<Marker<Grid>> const& marker) + { + marker_.push_back(marker); + if (marker_.size() > 1) + marker_.back()->setMaximumMarking(true); + } + + void addMarker(Marker<Grid>& marker) + { + addMarker(Dune::stackobject_to_shared_ptr(marker)); + } + /// Return the gridView of the leaf-level GridView const& gridView() { return globalBasis_->gridView(); } @@ -363,7 +376,10 @@ namespace AMDiS std::list<std::shared_ptr<FileWriterInterface>> filewriter_; /// Pointer to the adaptation markers - std::list<std::shared_ptr<Marker<Traits> > > marker_; + std::list<std::shared_ptr<Marker<Grid> > > marker_; + + /// Pointer to the estimators for this problem +// std::vector<Estimator*> estimator; /// An object of the linearSolver Interface std::shared_ptr<LinearSolverType> linearSolver_; diff --git a/src/amdis/ProblemStat.inc.hpp b/src/amdis/ProblemStat.inc.hpp index 56b904eb..e11503ba 100644 --- a/src/amdis/ProblemStat.inc.hpp +++ b/src/amdis/ProblemStat.inc.hpp @@ -120,6 +120,7 @@ void ProblemStat<Traits>::initialize( template <class Traits> void ProblemStat<Traits>::createMarker() { + marker_.clear(); auto localView = globalBasis_->localView(); AMDiS::forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath) { @@ -129,7 +130,7 @@ void ProblemStat<Traits>::createMarker() return; std::string tp = to_string(treePath); - auto newMarker = Marker<Traits>::createMarker(componentName, tp, estimates_[tp], grid_); + auto newMarker = EstimatorMarker<Grid>::createMarker(componentName, tp, estimates_[tp], grid_); if (newMarker) marker_.push_back(std::move(newMarker)); @@ -145,6 +146,7 @@ void ProblemStat<Traits>::createMarker() template <class Traits> void ProblemStat<Traits>::createFileWriter() { + filewriter_.clear(); auto localView = globalBasis_->localView(); forEachNode_(localView.tree(), [&,this](auto const& node, auto treePath) { @@ -223,7 +225,8 @@ solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData) template <class Traits> -Flag ProblemStat<Traits>::markElements(AdaptInfo& adaptInfo) +Flag ProblemStat<Traits>:: +markElements(AdaptInfo& adaptInfo) { Dune::Timer t; @@ -244,12 +247,18 @@ adaptGrid(AdaptInfo& adaptInfo) Dune::Timer t; grid_->preAdapt(); - grid_->adapt(); - globalBasis_->update(gridView()); + bool changed = grid_->adapt(); + + // update data + if (changed) { + globalBasis_->update(gridView()); + solution_->resize(*globalBasis_); + } + grid_->postAdapt(); msg("adaptGrid needed {} seconds", t.elapsed()); - return 0; + return changed ? MESH_ADAPTED : Flag(0); } diff --git a/src/amdis/ProblemStatBase.hpp b/src/amdis/ProblemStatBase.hpp index 20245e2b..9ba0b0b6 100644 --- a/src/amdis/ProblemStatBase.hpp +++ b/src/amdis/ProblemStatBase.hpp @@ -40,8 +40,7 @@ namespace AMDiS INIT_ADAPT | INIT_FILEWRITER | INIT_INITIAL_PROBLEM | INIT_UH_OLD | INIT_UPDATER | INIT_NONLIN_SOLVER ; - const Flag MESH_REFINED = 1; - const Flag MESH_COARSENED = 2; + const Flag MESH_ADAPTED = 1; // forward declaration class AdaptInfo; @@ -70,7 +69,7 @@ namespace AMDiS * matrices or vectors only. */ virtual void buildAfterAdapt(AdaptInfo& adaptInfo, Flag flag, - bool assembleMatrix, bool assembleVector) = 0; + bool assembleMatrix, bool assembleVector) = 0; /// Refinement/coarsening of the grid. virtual Flag adaptGrid(AdaptInfo& adaptInfo) = 0; diff --git a/src/amdis/StandardProblemIteration.cpp b/src/amdis/StandardProblemIteration.cpp index b65dfc8f..1c7047d6 100644 --- a/src/amdis/StandardProblemIteration.cpp +++ b/src/amdis/StandardProblemIteration.cpp @@ -63,10 +63,8 @@ namespace AMDiS if (toDo.isSet(MARK)) markFlag = problem_.markElements(adaptInfo); - else - markFlag = 3; - if (toDo.isSet(ADAPT) && (markFlag.isSet(MESH_REFINED) || markFlag.isSet(MESH_COARSENED))) + if (toDo.isSet(ADAPT) && markFlag.isSet(MESH_ADAPTED)) flag |= problem_.adaptGrid(adaptInfo); if (toDo.isSet(BUILD)) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index afb4a3cc..a18847f2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,6 +24,10 @@ dune_add_test(SOURCES FiniteElementTypeTest.cpp dune_add_test(SOURCES FilesystemTest.cpp LINK_LIBRARIES amdis) +dune_add_test(SOURCES MarkerTest.cpp + LINK_LIBRARIES amdis + CMD_ARGS "${CMAKE_SOURCE_DIR}/examples/init/marker.dat.2d") + dune_add_test(SOURCES MultiTypeVectorTest.cpp LINK_LIBRARIES amdis) diff --git a/test/MarkerTest.cpp b/test/MarkerTest.cpp new file mode 100644 index 00000000..f34e0f75 --- /dev/null +++ b/test/MarkerTest.cpp @@ -0,0 +1,59 @@ +#include <amdis/AMDiS.hpp> +#include <amdis/ProblemStat.hpp> + +#include "Tests.hpp" + +using namespace AMDiS; + +static const int d = 2; // problem dimension + +using Grid = Dune::UGGrid<d>; +using Basis = LagrangeBasis<Grid::LeafGridView, 1>; +using Problem = ProblemStat<Basis>; +using DomainType = typename Dune::FieldVector<double,d>; + +int main(int argc, char** argv) +{ + AMDiS::init(argc, argv); + + DomainType lowerLeft; lowerLeft = 0.0; // lower left grid corner + DomainType upperRight; upperRight = 1.0; // upper right grid corner + std::array<unsigned int, d> s; s.fill(1); // number of elements on each axis + + std::shared_ptr<Grid> grid = + Dune::StructuredGridFactory<Grid>::createCubeGrid(lowerLeft, upperRight, s); + + Problem prob("test", *grid); + prob.initialize(INIT_ALL); + + AdaptInfo adaptInfo("adapt"); + + // refine the grid close to the points (0, 0) and (1, 1) + auto markerFunc = [](auto const& x) -> double + { + static Dune::FieldVector<double, d> x0{0.0, 0.0}; + static Dune::FieldVector<double, d> x1{1.0, 1.0}; + return { 1.0 / (0.1 + std::min(distance(x0, x), distance(x1, x))) }; + }; + +#if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION + GridFunctionMarker marker("mymarker", grid, markerFunc); +#else + auto marker = makeGridFunctionMarker("mymarker", grid, markerFunc); +#endif + + prob.addMarker(marker); + + for (int i = 0; i < 10; ++i) { + prob.markElements(adaptInfo); + if (!prob.adaptGrid(adaptInfo)) + break; + } + + prob.getSolution().interpolate(markerFunc); + prob.writeFiles(adaptInfo); + + AMDiS::finalize(); + + return report_errors(); +} -- GitLab