From fb74a3a39b15b9ab8c72cae985ab79dde6b5120a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20M=C3=BCller?= <felix.mueller2@mailbox.tu-dresden.de> Date: Fri, 23 Mar 2018 15:11:38 +0100 Subject: [PATCH] Added class Marker based on AMDiS Marker class --- src/amdis/CMakeLists.txt | 2 + src/amdis/Marker.cpp | 278 ++++++++++++++++++++++++++++++++ src/amdis/Marker.hpp | 333 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 613 insertions(+) create mode 100644 src/amdis/Marker.cpp create mode 100644 src/amdis/Marker.hpp diff --git a/src/amdis/CMakeLists.txt b/src/amdis/CMakeLists.txt index 45e875a5..d2067008 100644 --- a/src/amdis/CMakeLists.txt +++ b/src/amdis/CMakeLists.txt @@ -8,6 +8,7 @@ dune_library_add_sources(amdis SOURCES AMDiS.cpp Initfile.cpp InitfileParser.cpp + Marker.cpp ProblemInstatBase.cpp # ProblemInstat.cpp ProblemStat.cpp @@ -36,6 +37,7 @@ install(FILES LinearAlgebra.hpp LocalAssembler.hpp LocalAssemblerBase.hpp + Marker.hpp Mesh.hpp Operations.hpp Operators.hpp diff --git a/src/amdis/Marker.cpp b/src/amdis/Marker.cpp new file mode 100644 index 00000000..877c30b5 --- /dev/null +++ b/src/amdis/Marker.cpp @@ -0,0 +1,278 @@ +// TODO: Cleanup of copied comments + +#include "Marker.hpp" + +#include <amdis/common/Math.hpp> + +namespace AMDiS { + + using std::pow; + + template <class Grid> + Marker<Grid>* Marker<Grid>::createMarker(std::string name, int row, const EstType& est, Grid* grid) + { + int strategy = 0; + Parameters::get(name + "->strategy", strategy); + + Marker *marker = NULL; + + switch (strategy) { + case 0: // no refinement/coarsening + break; + case 1: + msg("Creating global refinement (GR) marker\n"); + marker = new GRMarker<Grid>(name, row, est, grid); + break; + case 2: + msg("Creating maximum strategy (MS) marker\n"); + marker = new MSMarker<Grid>(name, row, est, grid); + break; + case 3: + msg("Creating equidistribution strategy (ES) marker\n"); + marker = new ESMarker<Grid>(name, row, est, grid); + break; + case 4: + msg("Creating guaranteed error reduction strategy (GERS) marker\n"); + marker = new GERSMarker<Grid>(name, row, est, grid); + break; + default: + error_exit("invalid strategy\n"); + } + + return marker; + } + + + + template <class Grid> + void Marker<Grid>::initMarking(AdaptInfo& adaptInfo) + { + int row_ = row == -1 ? 0 : row; + + elMarkRefine = 0; + elMarkCoarsen = 0; + estSum = pow(adaptInfo.getEstSum(row_), p); + estMax = adaptInfo.getEstMax(row_); + } + + + + template <class Grid> + void Marker<Grid>::finishMarking(AdaptInfo& adaptInfo) + { + msg(elMarkRefine, " elements marked for refinement\n"); + msg(elMarkCoarsen, " elements marked for coarsening\n"); + } + + + + template <class Grid> + void Marker<Grid>::markElement(AdaptInfo& adaptInfo, const Element& elem) + { + msg("DEBUG: Marker::markElement\n"); + int row_ = row == -1 ? 0 : row; + const auto& index = grid->leafIndexSet().index(elem); + double lError = est[index][row_]; + + if (adaptInfo.isRefinementAllowed(row_) && lError > markRLimit) { + if (maxRefineLevel == -1 || elem.level() < maxRefineLevel) { + this->mark(elem, 1); + } + } else { + if (adaptInfo.isCoarseningAllowed(row_) && lError <= markCLimit) { + if (minRefineLevel == -1 || elem.level() > minRefineLevel) { + if (/*!elem->getElementData()->getElementData(COARSENABLE) ||*/ + lError /*+ elem->getCoarseningEstimation(row)*/ <= markCLimit) { + this->mark(elem, -1); + } + } + } + } + } + + + + template <class Grid> + Flag Marker<Grid>::markGrid(AdaptInfo& adaptInfo) + { + msg("DEBUG: Marker::markGrid\n"); + + test_exit(grid, "No grid!\n"); + + initMarking(adaptInfo); + + int row_ = row == -1 ? 0 : row; + + if (!adaptInfo.isCoarseningAllowed(row_) && + !adaptInfo.isRefinementAllowed(row_)) { + return 0; + } + for (const auto& elem : Dune::elements(grid->leafGridView())) { + markElement(adaptInfo, elem); + } + + finishMarking(adaptInfo); + + Flag markFlag; + if (elMarkRefine) + markFlag = 1; + if (elMarkCoarsen) + markFlag |= 2; + + return markFlag; + } + + + template <class Grid> + void MSMarker<Grid>::initMarking(AdaptInfo& adaptInfo) + { + Marker<Grid>::initMarking(adaptInfo); + + int row_ = this->row == -1 ? 0 : this->row; + + double MSGammaP = pow(MSGamma, this->p); + double MSGammaCP = pow(MSGammaC, this->p); + + this->markRLimit = MSGammaP * adaptInfo.getEstMax(row_); + this->markCLimit = MSGammaCP * adaptInfo.getEstMax(row_); + + msg("start max_est: ", adaptInfo.getEstMax(row_), ", mark_limits: ", this->markRLimit, ", " , this->markCLimit, "\n"); + } + + + template <class Grid> + void ESMarker<Grid>::initMarking(AdaptInfo& adaptInfo) + { + Marker<Grid>::initMarking(adaptInfo); + + int row_ = this->row == -1 ? 0 : this->row; + + double ESThetaP = pow(ESTheta, this->p); + double ESThetaCP = pow(ESThetaC, this->p); + double epsP = pow(adaptInfo.getSpaceTolerance(row_), this->p); + + int nLeaves = (this->grid->leafGridView()).size(0); +/*#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::mpi::globalAdd(nLeaves); +#endif*/ + + this->markRLimit = ESThetaP * epsP / nLeaves; + this->markCLimit = ESThetaCP * epsP / nLeaves; + + msg("start mark_limits: ", this->markRLimit, ", " , this->markCLimit, "; nt = ", nLeaves , "\n"); + } + + + template <class Grid> + Flag GERSMarker<Grid>::markGrid(AdaptInfo& adaptInfo) + { + msg("DEBUG: GERSMarker::markGrid\n"); + + Marker<Grid>::initMarking(adaptInfo); + + int row_ = this->row == -1 ? 0 : this->row; + + if (!adaptInfo.isCoarseningAllowed(row_) && + !adaptInfo.isRefinementAllowed(row_)) + return 0; + + GERSSum = 0.0; + + double LTheta = pow(1.0 - GERSThetaStar, this->p); + double epsP = pow(adaptInfo.getSpaceTolerance(row_), this->p); + + if (this->estSum < oldErrSum) { + double improv = this->estSum / oldErrSum; + double wanted = 0.8 * epsP / this->estSum; + double redfac = std::min((1.0 - wanted) / (1.0 - improv), 1.0); + redfac = std::max(redfac, 0.0); + + if (redfac < 1.0) { + LTheta *= redfac; + msg("GERS: use extrapolated theta_star = ", pow(LTheta, 1.0 / this->p), "\n"); + } + } + + oldErrSum = this->estSum; + double GERSGamma = 1.0; + + if (adaptInfo.isRefinementAllowed(row_)) { + if (LTheta > 0) { + do { + GERSSum = 0.0; + GERSGamma -= GERSNu; + this->markRLimit = GERSGamma * this->estMax; + + for (const auto& elem : Dune::elements(this->grid->leafGridView())) + markElementForRefinement(adaptInfo, elem); + + } while((GERSGamma > 0) && (GERSSum < LTheta * this->estSum)); + } + + msg("GERS refinement with gamma = ", GERSGamma, "\n"); + } + + if (adaptInfo.isCoarseningAllowed(row_)) { + GERSGamma = 0.3; + LTheta = GERSThetaC * epsP; + + do { + GERSSum = 0.0; + GERSGamma -= GERSNu; + this->markCLimit = GERSGamma * this->estMax; + + for (const auto& elem : Dune::elements(this->grid->leafGridView())) + markElementForCoarsening(adaptInfo, elem); + + msg("coarse loop: gamma = ", GERSGamma, ", sum = ", GERSSum, ", limit = ", LTheta, "\n"); + } while(GERSSum > LTheta); + + msg("GERS coarsening with gamma = ", GERSGamma, "\n"); + } + + Marker<Grid>::finishMarking(adaptInfo); + + Flag markFlag; + if (this->elMarkRefine) + markFlag = 1; + if (this->elMarkCoarsen) + markFlag |= 2; + + return(markFlag); + } + + + template <class Grid> + void GERSMarker<Grid>::markElementForRefinement(AdaptInfo& adaptInfo, const Element& elem) + { + int row_ = this->row == -1 ? 0 : this->row; + double lError = (this->est)[(this->grid->leafIndexSet()).index(elem)][row_]; + + if (lError > this->markRLimit) { + GERSSum += lError; + this->mark(elem, 1); + } + } + + + template <class Grid> + void GERSMarker<Grid>::markElementForCoarsening(AdaptInfo& adaptInfo, const Element& elem) + { + int row_ = this->row == -1 ? 0 : this->row; + double lError = (this->est)[(this->grid->leafIndexSet()).index(elem)][row_]; + + if ((this->grid)->getMark(elem) <= 0) { +/* if (elem->getElementData()->getElementData(COARSENABLE))*/ +/* lError += elem->getCoarseningEstimation(row);*/ + + if (lError <= this->markCLimit) { + GERSSum += lError; + this->mark(elem, -1); + } else { + this->mark(elem, 0); + } + } + } + + +} diff --git a/src/amdis/Marker.hpp b/src/amdis/Marker.hpp new file mode 100644 index 00000000..9817e216 --- /dev/null +++ b/src/amdis/Marker.hpp @@ -0,0 +1,333 @@ +#pragma once +// TODO: Cleanup of copied comments +#include <string> + +#include <dune/grid/common/grid.hh> + +#include <amdis/AdaptInfo.hpp> +#include <amdis/Flag.hpp> +#include <amdis/Initfile.hpp> + +namespace AMDiS { + + + /** + * \ingroup Adaption + * + * \brief + * Base class for all scalar markers. + */ + template <class Grid> + class Marker + { + + using GridView = typename Grid::LeafGridView; + using IndexSet = typename GridView::IndexSet; + using Element = typename GridView::template Codim<0>::Entity; + using EstType = std::vector<std::vector<double> >; + + public: + /// Constructor. + Marker() {} + + /// Constructor. + Marker(std::string name_, int row_, const EstType& est_, Grid* grid_) + : name(name_), + row(row_), + grid(grid_), + est(est_), + maximumMarking(false), + p(2), + info(10), + maxRefineLevel(-1), + minRefineLevel(-1) + { + 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() {} + + /// 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. + inline void mark(const Element& elem, int newMark) + { + int oldMark = grid->getMark(elem); + + if (!maximumMarking || (newMark > oldMark)) { + bool (marked) = grid->mark(newMark, elem); + msg("DEBUG: Was marked? ", marked, "; oldMark = ", oldMark, ", newMark = ", newMark, "\n"); + if (marked) { + if (oldMark > 0) { + elMarkRefine--; + } else if (oldMark < 0) { + elMarkCoarsen--; + } + + if (newMark > 0) { + elMarkRefine++; + } else if (newMark < 0) { + elMarkCoarsen++; + } + } else { + msg("Marking failed"); + } + } + } + + /// Can be used by sub classes. Called before traversal. + virtual void initMarking(AdaptInfo& adaptInfo); + + /// Can be used by sub classes. Called after traversal. + virtual void finishMarking(AdaptInfo& adaptInfo); + + /// Marks one element. + virtual void markElement(AdaptInfo& adaptInfo, const Element& elem); + + /// Marking of the mesh. + virtual Flag markGrid(AdaptInfo& adaptInfo); + + /// Sets \ref maximumMarking. + inline void setMaximumMarking(bool maxMark) + { + maximumMarking = maxMark; + } + + inline int getElMarkRefine() + { + return elMarkRefine; + } + + inline int getElMarkCoarsen() + { + return elMarkCoarsen; + } + + /// Returns \ref name of the Marker + inline std::string getName() const + { + return name; + } + + /// Creates a scalar marker depending on the strategy set in parameters. + static Marker<Grid>* createMarker(std::string name, int row_, const EstType& est_, Grid* grid_); + + protected: + /// Name of the scalar marker. + std::string name; + + /// Equal to -1 for scalar problems. Component number if marker is + /// part of a vector valued marker. + int row; + + /// Pointer to the grid + Grid* grid; + + /// Pointer to the local error estimates + EstType est; + + /// estimation sum + double estSum; + + /// estmation maximum + double estMax; + + /// 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 + double p; + + /// Info level. + int info; + + /// Counter for elements marked for refinement + int elMarkRefine; + + /// Counter for elements marked for coarsening + int elMarkCoarsen; + + /// Maximal level of all elements. + int maxRefineLevel; + + /// Minimal level of all elements. + int minRefineLevel; + }; + + + /** + * \ingroup Adaption + * + * \brief + * Global refinement. + */ + template <class Grid> + class GRMarker : public Marker<Grid> + { + using GridView = typename Grid::LeafGridView; + using IndexSet = typename GridView::IndexSet; + using Element = typename GridView::template Codim<0>::Entity; + using EstType = std::vector<std::vector<double> >; + + public: + /// Constructor. + GRMarker(std::string name_, int row_, const EstType& est_, Grid* grid_) + : Marker<Grid>(name_, row_, est_, grid_) + {} + + /// Implementation of Marker::markElement(). + virtual void markElement(AdaptInfo& adaptInfo, const Element& elem) + { + msg("DEBUG: GRMarker::markElement\n"); + if (adaptInfo.isRefinementAllowed(this->row == -1 ? 0 : this->row)) + this->mark(elem, 1); + } + }; + + + /** + * \ingroup Adaption + * + * \brief + * Maximum strategy. + */ + + template <class Grid> + class MSMarker : public Marker<Grid> + { + using GridView = typename Grid::LeafGridView; + using IndexSet = typename GridView::IndexSet; + using Element = typename GridView::template Codim<0>::Entity; + using EstType = std::vector<std::vector<double> >; + + public: + /// Constructor. + MSMarker(std::string name_, int row_, const EstType& est_, Grid* grid_) + : Marker<Grid>(name_, row_, est_, grid_), + MSGamma(0.5), + MSGammaC(0.1) + { + Parameters::get(this->name + "->MSGamma", MSGamma); + Parameters::get(this->name + "->MSGammaC", MSGammaC); + } + + /// Implementation of Marker::initMarking(). + void initMarking(AdaptInfo& adaptInfo); + + protected: + /// Marking parameter. + double MSGamma; + + /// Marking parameter. + double MSGammaC; + }; + + + /** + * \ingroup Adaption + * + * \brief + * Equidistribution strategy + */ + + template <class Grid> + class ESMarker : public Marker<Grid> + { + using GridView = typename Grid::LeafGridView; + using IndexSet = typename GridView::IndexSet; + using Element = typename GridView::template Codim<0>::Entity; + using EstType = std::vector<std::vector<double> >; + + public: + /// Constructor. + ESMarker(std::string name_, int row_, const EstType& est_, Grid* grid_) + : Marker<Grid>(name_, row_, est_, grid_), + ESTheta(0.9), + ESThetaC(0.2) + { + Parameters::get(this->name + "->ESTheta", ESTheta); + Parameters::get(this->name + "->ESThetaC", ESThetaC); + } + + /// Implementation of Marker::initMarking(). + virtual void initMarking(AdaptInfo& adaptInfo); + + protected: + /// Marking parameter. + double ESTheta; + + /// Marking parameter. + double ESThetaC; + }; + + + /** + * \ingroup Adaption + * + * \brief + * Guaranteed error reduction strategy + */ + + template <class Grid> + class GERSMarker : public Marker<Grid> + { + using GridView = typename Grid::LeafGridView; + using IndexSet = typename GridView::IndexSet; + using Element = typename GridView::template Codim<0>::Entity; + using EstType = std::vector<std::vector<double> >; + + public: + /// Constructor. + GERSMarker(std::string name_, int row_, const EstType& est_, Grid* grid_) + : Marker<Grid>(name_, row_, est_, grid_), + oldErrSum(0.0), + GERSThetaStar(0.6), + GERSNu(0.1), + GERSThetaC(0.1) + { + Parameters::get(this->name + "->GERSThetaStar", GERSThetaStar); + Parameters::get(this->name + "->GERSNu", GERSNu); + Parameters::get(this->name + "->GERSThetaC", GERSThetaC); + } + + /// Implementation of Marker::markGrid(). + virtual Flag markGrid(AdaptInfo& adaptInfo); + + protected: + /// Refinement marking function. + void markElementForRefinement(AdaptInfo& adaptInfo, const Element& elem); + + /// Coarsening marking function. + void markElementForCoarsening(AdaptInfo& adaptInfo, const Element& elem); + + protected: + /// Marking parameter. + double GERSSum; + + /// Marking parameter. + double oldErrSum; + + /// Marking parameter. + double GERSThetaStar; + + /// Marking parameter. + double GERSNu; + + /// Marking parameter. + double GERSThetaC; + }; + +} -- GitLab