Am Montag, 13. Mai 2022, finden Wartungsarbeiten am Gitlab-Server (Update auf neue Version statt). Der Dienst wird daher am Montag für einige Zeit nicht verfügbar sein.
On Monday, May 13th 2022, the Gitlab server will be updated. The service will therefore not be accessible for some time on Monday.

Commit fb74a3a3 authored by Müller, Felix's avatar Müller, Felix Committed by Praetorius, Simon
Browse files

Added class Marker based on AMDiS Marker class

parent 9f7667fc
......@@ -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
......
// 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);
}
}
}
}
#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;
};