Commit ee65b18e authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

GridFunctionMarker

parent 048ac58b
dimension of world: 2
test->mesh: testMesh
testMesh->global refinements: 0
#pragma once #pragma once
#include <limits>
#include <string> #include <string>
#include <utility>
#include <dune/common/std/optional.hh>
#include <dune/grid/common/grid.hh> #include <dune/grid/common/grid.hh>
#include <amdis/common/ConceptsBase.hpp>
#include <amdis/gridfunctions/GridFunctionConcepts.hpp>
#include <amdis/AdaptInfo.hpp> #include <amdis/AdaptInfo.hpp>
#include <amdis/Flag.hpp> #include <amdis/Flag.hpp>
#include <amdis/Initfile.hpp> #include <amdis/Initfile.hpp>
namespace AMDiS { namespace AMDiS
{
/** /**
* \ingroup Adaption * \ingroup Adaption
* *
* \brief * \brief
* Base class for all scalar markers. * Base class for all markers.
*/ */
template <class Traits> template <class Grid>
class Marker class Marker
{ {
protected: protected:
using GlobalBasis = typename Traits::GlobalBasis; using GridView = typename Grid::LeafGridView;
using GridView = typename GlobalBasis::GridView;
using Grid = typename GridView::Grid;
using IndexSet = typename GridView::IndexSet;
using Element = typename GridView::template Codim<0>::Entity; using Element = typename GridView::template Codim<0>::Entity;
using Estimates = std::vector<double>;
public: public:
/// Constructor. /// Constructor.
Marker() {} Marker() = default;
/// Constructor. /// Constructor.
Marker(std::string const& name, std::string const& component, Estimates const& est, Marker(std::string const& name, std::shared_ptr<Grid> const& grid)
std::shared_ptr<Grid> const& grid)
: name_(name) : name_(name)
, component_(component)
, grid_(grid) , grid_(grid)
, est_(est)
, maximumMarking_(false)
{ {
Parameters::get(name + "->p", p_);
Parameters::get(name + "->info", info_); Parameters::get(name + "->info", info_);
Parameters::get(name + "->max refinement level", maxRefineLevel_); Parameters::get(name + "->max refinement level", maxRefineLevel_);
Parameters::get(name + "->min refinement level", minRefineLevel_); Parameters::get(name + "->min refinement level", minRefineLevel_);
} }
/// destructor /// Destructor.
virtual ~Marker() {} virtual ~Marker() = default;
/// Marks element with newMark. If \ref maximumMarking_ is set, the element /// 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 /// 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. /// value specifies whether the element has been marked, or not.
void mark(Element const& elem, int newMark) 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");
}
}
}
/// Can be used by sub classes. Called before traversal. /// Called before traversal.
virtual void initMarking(AdaptInfo& adaptInfo); virtual void initMarking(AdaptInfo& adaptInfo);
/// Can be used by sub classes. Called after traversal. /// Called after traversal.
virtual void finishMarking(AdaptInfo& adaptInfo); virtual void finishMarking(AdaptInfo& adaptInfo);
/// Marks one element. /// 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); virtual Flag markGrid(AdaptInfo& adaptInfo);
/// Sets \ref maximumMarking. /// Returns \ref elMarkRefine_ of the Marker
void setMaximumMarking(bool maxMark) int getElMarkRefine() const
{
maximumMarking_ = maxMark;
}
int getElMarkRefine()
{ {
return elMarkRefine_; return elMarkRefine_;
} }
int getElMarkCoarsen() /// Returns \ref elMarkCoarsen_ of the Marker
int getElMarkCoarsen() const
{ {
return elMarkCoarsen_; return elMarkCoarsen_;
} }
/// Returns \ref name of the Marker /// Returns \ref name_ of the Marker
std::string const& getName() const std::string getName() const
{ {
return name_; return name_;
} }
/// Creates a scalar marker depending on the strategy set in parameters. /// Sets \ref maximumMarking_.
static std::unique_ptr<Marker<Traits> > createMarker(std::string const& name, std::string const& component, Estimates const& est, std::shared_ptr<Grid> const& grid); 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: protected:
/// Name of the scalar marker. /// Name of the marker.
std::string name_; std::string name_;
/// Problem component to work on
std::string component_;
/// Pointer to the grid /// Pointer to the grid
std::shared_ptr<Grid> 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 /// If true, elements are marked only if the new value is bigger than
/// the current marking. /// the current marking.
bool maximumMarking_; bool maximumMarking_ = false;
/// 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;
/// Info level. /// Info level.
int info_ = 10; int info_ = 0;
/// Counter for elements marked for refinement /// Counter for elements marked for refinement
int elMarkRefine_ = 0; int elMarkRefine_ = 0;
...@@ -163,9 +126,76 @@ namespace AMDiS { ...@@ -163,9 +126,76 @@ namespace AMDiS {
/// Minimal level of all elements. /// Minimal level of all elements.
int minRefineLevel_ = -1; int minRefineLevel_ = -1;
/// Allow elements to be marked for refinement
bool refineAllowed_ = true; 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 { ...@@ -175,24 +205,22 @@ namespace AMDiS {
* \brief * \brief
* Global refinement. * Global refinement.
*/ */
template <class Traits> template <class Grid>
class GRMarker class GRMarker
: public Marker<Traits> : public EstimatorMarker<Grid>
{ {
using Super = Marker<Traits>; using Super = EstimatorMarker<Grid>;
using Grid = typename Super::Grid;
using Element = typename Super::Element; using Element = typename Super::Element;
using Estimates = typename Super::Estimates; using Estimates = typename Super::Estimates;
public: public:
/// Constructor. /// 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) 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) override
virtual void markElement(AdaptInfo& adaptInfo, Element const& elem)
{ {
if (this->refineAllowed_) if (this->refineAllowed_)
this->mark(elem, 1); this->mark(elem, 1);
...@@ -207,12 +235,11 @@ namespace AMDiS { ...@@ -207,12 +235,11 @@ namespace AMDiS {
* Maximum strategy. * Maximum strategy.
*/ */
template <class Traits> template <class Grid>
class MSMarker class MSMarker
: public Marker<Traits> : public EstimatorMarker<Grid>
{ {
using Super = Marker<Traits>; using Super = EstimatorMarker<Grid>;
using Grid = typename Super::Grid;
using Estimates = typename Super::Estimates; using Estimates = typename Super::Estimates;
public: public:
...@@ -225,8 +252,7 @@ namespace AMDiS { ...@@ -225,8 +252,7 @@ namespace AMDiS {
Parameters::get(name + "->MSGammaC", msGammaC_); Parameters::get(name + "->MSGammaC", msGammaC_);
} }
/// Implementation of Marker::initMarking(). virtual void initMarking(AdaptInfo& adaptInfo) override;
void initMarking(AdaptInfo& adaptInfo);
protected: protected:
/// Marking parameter. /// Marking parameter.
...@@ -244,12 +270,11 @@ namespace AMDiS { ...@@ -244,12 +270,11 @@ namespace AMDiS {
* Equidistribution strategy * Equidistribution strategy
*/ */
template <class Traits> template <class Grid>
class ESMarker class ESMarker
: public Marker<Traits> : public EstimatorMarker<Grid>
{ {
using Super = Marker<Traits>; using Super = EstimatorMarker<Grid>;
using Grid = typename Super::Grid;
using Estimates = typename Super::Estimates; using Estimates = typename Super::Estimates;
public: public:
...@@ -262,8 +287,7 @@ namespace AMDiS { ...@@ -262,8 +287,7 @@ namespace AMDiS {
Parameters::get(name + "->ESThetaC", esThetaC_); Parameters::get(name + "->ESThetaC", esThetaC_);
} }
/// Implementation of Marker::initMarking(). virtual void initMarking(AdaptInfo& adaptInfo) override;
virtual void initMarking(AdaptInfo& adaptInfo);
protected: protected:
/// Marking parameter. /// Marking parameter.
...@@ -281,12 +305,11 @@ namespace AMDiS { ...@@ -281,12 +305,11 @@ namespace AMDiS {
* Guaranteed error reduction strategy * Guaranteed error reduction strategy
*/ */
template <class Traits> template <class Grid>
class GERSMarker class GERSMarker
: public Marker<Traits> : public EstimatorMarker<Grid>
{ {
using Super = Marker<Traits>; using Super = EstimatorMarker<Grid>;
using Grid = typename Super::Grid;
using Element = typename Super::Element; using Element = typename Super::Element;
using Estimates = typename Super::Estimates; using Estimates = typename Super::Estimates;
...@@ -301,8 +324,7 @@ namespace AMDiS { ...@@ -301,8 +324,7 @@ namespace AMDiS {
Parameters::get(name + "->GERSThetaC", gersThetaC_); Parameters::get(name + "->GERSThetaC", gersThetaC_);
} }
/// Implementation of Marker::markGrid(). virtual Flag markGrid(AdaptInfo& adaptInfo) override;
virtual Flag markGrid(AdaptInfo& adaptInfo);
protected: protected:
/// Refinement marking function. /// Refinement marking function.
...@@ -328,6 +350,86 @@ namespace AMDiS { ...@@ -328,6 +350,86 @@ namespace AMDiS {
double gersThetaC_ = 0.1; 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" #include "Marker.inc.hpp"
...@@ -2,105 +2,134 @@ ...@@ -2,105 +2,134 @@
namespace AMDiS { namespace AMDiS {
template <class Traits> template <class Grid>
std::unique_ptr<Marker<Traits> > Marker<Traits>:: void Marker<Grid>::mark(Element const& elem, int newMark)
createMarker(std::string const& name, std::string const& component,
Estimates const& est, std::shared_ptr<Grid> const& grid)
{ {
int strategy = 0; int oldMark = grid_->getMark(elem);
Parameters::get(name + "->strategy", strategy);
if (!maximumMarking_ || (newMark > oldMark)) {
switch (strategy) { bool marked = grid_->mark(newMark, elem);
case 0: // no refinement/coarsening if (marked) {
break; if (oldMark > 0) {
case 1: elMarkRefine_--;
msg("Creating global refinement (GR) marker"); } else if (oldMark < 0) {
return std::make_unique<GRMarker<Traits> >(name, component, est, grid); elMarkCoarsen_--;
break; }
case 2:
msg("Creating maximum strategy (MS) marker"); if (newMark > 0) {
return std::make_unique<MSMarker<Traits> >(name, component, est, grid); elMarkRefine_++;
break; } else if (newMark < 0) {
case 3: elMarkCoarsen_++;
msg("Creating equidistribution strategy (ES) marker"); }
return std::make_unique<ESMarker<Traits> >(name, component, est, grid); } else {
break; msg("Marking failed");
case 4: }
msg("Creating guaranteed error reduction strategy (GERS) marker");