Commit 5de011fb authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

RecoveryEstimator modified to have a structure similar to ResidualEstimator

parent 04249ebf
...@@ -772,12 +772,12 @@ namespace AMDiS { ...@@ -772,12 +772,12 @@ namespace AMDiS {
assembleFlag); assembleFlag);
} }
if (asmMatrix) { // if (asmMatrix) {
solverMatrix.setMatrix(*systemMatrix); solverMatrix.setMatrix(*systemMatrix);
createPrecon(); createPrecon();
INFO(info, 8)("fillin of assembled matrix: %d\n", nnz); INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
} // }
#ifdef _OPENMP #ifdef _OPENMP
INFO(info, 8)("buildAfterCoarsen needed %.5f seconds system time / %.5f seconds wallclock time\n", INFO(info, 8)("buildAfterCoarsen needed %.5f seconds system time / %.5f seconds wallclock time\n",
......
...@@ -15,12 +15,13 @@ ...@@ -15,12 +15,13 @@
namespace AMDiS { namespace AMDiS {
RecoveryEstimator::RecoveryEstimator(std::string name, DOFVector<double> *uh, int r) RecoveryEstimator::RecoveryEstimator(std::string name, DOFVector<double> *uh_, int r)
: Estimator(name, r), : Estimator(name, r),
uh_(uh), uh(uh_),
relative_(0), relative(0),
C(1.0), C(1.0),
method(0), method(0),
addEstimationToOld(false),
feSpace(NULL), feSpace(NULL),
f_vec(NULL), f_vec(NULL),
f_scal(NULL), f_scal(NULL),
...@@ -29,14 +30,14 @@ namespace AMDiS { ...@@ -29,14 +30,14 @@ namespace AMDiS {
{ {
FUNCNAME("RecoveryEstimator::constructor()"); FUNCNAME("RecoveryEstimator::constructor()");
GET_PARAMETER(0, name + "->rec method", "%d", &method); GET_PARAMETER(0, name + "->rec method", "%d", &method); // 0, 1, or 2 (see Recovery.h)
GET_PARAMETER(0, name + "->rel error", "%d", &relative_); GET_PARAMETER(0, name + "->rel error", "%d", &relative); // 0 or 1
GET_PARAMETER(0, name + "->C", "%f", &C); GET_PARAMETER(0, name + "->C", "%f", &C);
C = C > 1e-25 ? sqr(C) : 1.0; C = C > 1e-25 ? sqr(C) : 1.0;
if (norm == H1_NORM) { if (norm == H1_NORM) {
feSpace = uh->getFeSpace(); feSpace = uh_->getFeSpace();
degree = feSpace->getBasisFcts()->getDegree(); degree = feSpace->getBasisFcts()->getDegree();
if (degree <= 2 && C != 1.0) { if (degree <= 2 && C != 1.0) {
...@@ -44,10 +45,10 @@ namespace AMDiS { ...@@ -44,10 +45,10 @@ namespace AMDiS {
WAIT; WAIT;
} }
} else { } else {
degree = uh->getFeSpace()->getBasisFcts()->getDegree() + 1; degree = uh_->getFeSpace()->getBasisFcts()->getDegree() + 1;
feSpace = FiniteElemSpace::provideFeSpace(NULL, feSpace = FiniteElemSpace::provideFeSpace(NULL,
Lagrange::getLagrange(uh->getFeSpace()->getMesh()->getDim(), degree), Lagrange::getLagrange(uh_->getFeSpace()->getMesh()->getDim(), degree),
uh->getFeSpace()->getMesh(), uh_->getFeSpace()->getMesh(),
name + "->feSpace"); name + "->feSpace");
if (method == 2) { if (method == 2) {
...@@ -66,72 +67,114 @@ namespace AMDiS { ...@@ -66,72 +67,114 @@ namespace AMDiS {
rec_struct = new Recovery(norm, method); rec_struct = new Recovery(norm, method);
} }
void RecoveryEstimator::init(double ts)
double RecoveryEstimator::estimate(double timestep)
{ {
FUNCNAME("RecoveryEstimator::estimate()"); FUNCNAME("RecoveryEstimator::init()");
const BasisFunction *basFcts = uh_->getFeSpace()->getBasisFcts(); basFcts = uh->getFeSpace()->getBasisFcts();
Mesh *mesh = uh_->getFeSpace()->getMesh();
int dim = mesh->getDim(); int dim = mesh->getDim();
int dow = Global::getGeo(WORLD); h1Norm2 = 0.0;
double h1Norm2 = 0.0;
if (norm == H1_NORM) { // sets recovery gradient. if (norm == H1_NORM) { // sets recovery gradient.
if (method == 2) if (method == 2)
rec_grd = rec_struct->recovery(uh_, f_vec, f_scal, aux_vec); rec_grd = rec_struct->recovery(uh, f_vec, f_scal, aux_vec);
else else
rec_grd = rec_struct->recovery(uh_, feSpace, f_vec, f_scal, aux_vec); rec_grd = rec_struct->recovery(uh, feSpace, f_vec, f_scal, aux_vec);
rec_basFcts = rec_grd->getFeSpace()->getBasisFcts(); rec_basFcts = rec_grd->getFeSpace()->getBasisFcts();
} else { // sets higher-order recovery solution. } else { // sets higher-order recovery solution.
rec_uh = rec_struct->recoveryUh(uh_, feSpace); rec_uh = rec_struct->recoveryUh(uh, feSpace);
rec_basFcts = rec_uh->getFeSpace()->getBasisFcts(); rec_basFcts = rec_uh->getFeSpace()->getBasisFcts();
} }
int deg = 2 * std::max(basFcts->getDegree(), rec_basFcts->getDegree()); int deg = 2 * std::max(basFcts->getDegree(), rec_basFcts->getDegree());
Quadrature *quad = Quadrature::provideQuadrature(dim, deg); quad = Quadrature::provideQuadrature(dim, deg);
int nPoints = quad->getNumPoints(); nPoints = quad->getNumPoints();
WorldVector<double> quad_pt; // WorldVector<double> quad_pt;
WorldVector<double> *grdAtQP = new WorldVector<double>[nPoints]; grdAtQP = new WorldVector<double>[nPoints];
mtl::dense_vector<WorldVector<double> > recoveryGrdAtQP(nPoints); recoveryGrdAtQP = mtl::dense_vector<WorldVector<double> >(nPoints);
mtl::dense_vector<double> uhAtQP(nPoints), recoveryUhAtQP(nPoints); uhAtQP = mtl::dense_vector<double>(nPoints);
recoveryUhAtQP = mtl::dense_vector<double>(nPoints);
FastQuadrature *quadFast =
FastQuadrature::provideFastQuadrature(basFcts, *quad, INIT_PHI | INIT_GRD_PHI);
FastQuadrature *rec_quadFast =
FastQuadrature::provideFastQuadrature(rec_basFcts, *quad, INIT_PHI | INIT_GRD_PHI);
quadFast = FastQuadrature::provideFastQuadrature(basFcts, *quad, INIT_PHI | INIT_GRD_PHI);
rec_quadFast = FastQuadrature::provideFastQuadrature(rec_basFcts, *quad, INIT_PHI | INIT_GRD_PHI);
// clear error indicators // clear error indicators
if(!addEstimationToOld) {
TraverseStack stack; TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
while (elInfo) { while (elInfo) {
elInfo->getElement()->setEstimation(0.0, row); elInfo->getElement()->setEstimation(0.0, row);
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
} }
}
est_sum = 0.0;
est_max = 0.0;
est_t_sum = 0.0;
est_t_max = 0.0;
traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_DET | Mesh::FILL_GRD_LAMBDA;
}
void RecoveryEstimator::exit(bool output)
{
FUNCNAME("RecoveryEstimator::exit()");
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
double send_est_sum = est_sum;
double send_est_max = est_max;
// traverse mesh MPI::COMM_WORLD.Allreduce(&send_est_sum, &est_sum, 1, MPI_DOUBLE, MPI_SUM);
est_sum = est_max = est_t_sum = 0.0; MPI::COMM_WORLD.Allreduce(&send_est_max, &est_max, 1, MPI_DOUBLE, MPI_MAX);
#endif
// Computing relative errors
if (relative) {
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
while (elInfo) {
double estEl = elInfo->getElement()->getEstimation(row);
estEl /= h1Norm2;
elInfo->getElement()->setEstimation(estEl, row);
elInfo = stack.traverseNext(elInfo);
}
est_max /= h1Norm2;
est_sum /= h1Norm2;
}
est_sum = sqrt(est_sum);
delete [] grdAtQP;
elInfo = stack.traverseFirst(mesh, -1, if (output) {
Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | MSG("estimate for component %d = %.8e\n", row, est_sum);
Mesh::FILL_DET | Mesh::FILL_GRD_LAMBDA); }
while (elInfo) { }
void RecoveryEstimator::estimateElement(ElInfo *elInfo, DualElInfo *dualElInfo)
{
FUNCNAME("RecoveryEstimator::estimateElement()");
Element *el = elInfo->getElement(); Element *el = elInfo->getElement();
double det = elInfo->getDet(); double det = elInfo->getDet();
double errEl = 0.0; double errEl = 0.0;
double estEl = el->getEstimation(row);
int dow = Global::getGeo(WORLD);
if (norm == H1_NORM) { if (norm == H1_NORM) {
// get gradient and recovery gradient at quadrature points // get gradient and recovery gradient at quadrature points
uh_->getGrdAtQPs(elInfo, NULL, quadFast, grdAtQP); uh->getGrdAtQPs(elInfo, NULL, quadFast, grdAtQP);
rec_grd->getVecAtQPs(elInfo, NULL, rec_quadFast, recoveryGrdAtQP); rec_grd->getVecAtQPs(elInfo, NULL, rec_quadFast, recoveryGrdAtQP);
if (f_scal) { if (f_scal) {
if (aux_vec) if (aux_vec)
aux_vec->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP); aux_vec->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP);
else else
uh_->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP); uh->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP);
} }
// calc h1 error // calc h1 error
...@@ -151,7 +194,7 @@ namespace AMDiS { ...@@ -151,7 +194,7 @@ namespace AMDiS {
} }
} else { } else {
// get vector and recovery vector at quadrature points // get vector and recovery vector at quadrature points
uh_->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP); uh->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP);
rec_uh->getVecAtQPs(elInfo, NULL, rec_quadFast, recoveryUhAtQP); rec_uh->getVecAtQPs(elInfo, NULL, rec_quadFast, recoveryUhAtQP);
// calc l2 error // calc l2 error
...@@ -159,12 +202,12 @@ namespace AMDiS { ...@@ -159,12 +202,12 @@ namespace AMDiS {
errEl += quad->getWeight(i) * sqr(recoveryUhAtQP[i] - uhAtQP[i]); errEl += quad->getWeight(i) * sqr(recoveryUhAtQP[i] - uhAtQP[i]);
} }
double estEl = C * det * errEl; estEl += C * det * errEl;
el->setEstimation(estEl, row); el->setEstimation(estEl, row);
est_sum += estEl; est_sum += estEl;
est_max = std::max(est_max, estEl); est_max = std::max(est_max, estEl);
if (relative_) { if (relative) {
double normEl = 0.0; double normEl = 0.0;
if (norm == H1_NORM) { if (norm == H1_NORM) {
...@@ -181,31 +224,6 @@ namespace AMDiS { ...@@ -181,31 +224,6 @@ namespace AMDiS {
h1Norm2 += det * normEl; h1Norm2 += det * normEl;
} }
elInfo = stack.traverseNext(elInfo);
}
// Computing relative errors
if (relative_) {
elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
while (elInfo) {
double estEl = elInfo->getElement()->getEstimation(row);
estEl /= h1Norm2;
elInfo->getElement()->setEstimation(estEl, row);
elInfo = stack.traverseNext(elInfo);
}
est_max /= h1Norm2;
est_sum /= h1Norm2;
}
est_sum = sqrt(est_sum);
delete [] grdAtQP;
MSG("estimate = %.8e\n", est_sum);
return est_sum;
} }
} }
...@@ -59,19 +59,24 @@ namespace AMDiS { ...@@ -59,19 +59,24 @@ namespace AMDiS {
}; };
/// constructor /// constructor
RecoveryEstimator(std::string name, DOFVector<double> *uh, int r = -1); RecoveryEstimator(std::string name, DOFVector<double> *uh_, int r = -1);
/// destructor. /// destructor.
virtual ~RecoveryEstimator() {} virtual ~RecoveryEstimator() {}
/// implements \ref Estimator::estimate(). /// implements \ref Estimator::init(double).
virtual double estimate(double timestep = 0.0); void init(double ts);
/// implements \ref Estimator::estimateElement(ElInfo*, DualElInfo*).
void estimateElement(ElInfo *elInfo, DualElInfo *dualElInfo);
/// implements \ref Estimator::exit(bool).
void exit(bool output);
/// Sets uh. /// Sets uh.
inline void setUh(DOFVector<double> *uh) inline void setUh(DOFVector<double> *uh_)
{ {
uh_ = uh; uh = uh_;
} }
/// Sets f. /// Sets f.
...@@ -92,6 +97,10 @@ namespace AMDiS { ...@@ -92,6 +97,10 @@ namespace AMDiS {
aux_vec = uh; aux_vec = uh;
} }
inline void setAddEstimationToOld(bool value)
{
addEstimationToOld = value;
}
/// Gets recovery gradient. /// Gets recovery gradient.
inline DOFVector<WorldVector<double> >* getRecGrd() inline DOFVector<WorldVector<double> >* getRecGrd()
...@@ -108,10 +117,10 @@ namespace AMDiS { ...@@ -108,10 +117,10 @@ namespace AMDiS {
protected: protected:
/// finite element solution /// finite element solution
DOFVector<double> *uh_; DOFVector<double> *uh;
/// absolute or relative error? /// absolute or relative error?
int relative_; int relative;
/// constant for scaling the estimator /// constant for scaling the estimator
double C; double C;
...@@ -119,6 +128,8 @@ namespace AMDiS { ...@@ -119,6 +128,8 @@ namespace AMDiS {
/// recovery method /// recovery method
int method; int method;
bool addEstimationToOld;
/// Working finite element space /// Working finite element space
const FiniteElemSpace *feSpace; const FiniteElemSpace *feSpace;
...@@ -143,6 +154,23 @@ namespace AMDiS { ...@@ -143,6 +154,23 @@ namespace AMDiS {
/// Recovery structure. /// Recovery structure.
Recovery *rec_struct; Recovery *rec_struct;
/// Number of quadrature points.
int nPoints;
Quadrature *quad;
FastQuadrature *quadFast, *rec_quadFast;
/// Basis functions
const BasisFunction *basFcts;
double h1Norm2;
WorldVector<double> quad_pt;
WorldVector<double> *grdAtQP;
mtl::dense_vector<WorldVector<double> > recoveryGrdAtQP;
mtl::dense_vector<double> uhAtQP;
mtl::dense_vector<double> recoveryUhAtQP;
}; };
} }
......
...@@ -87,19 +87,24 @@ namespace AMDiS { ...@@ -87,19 +87,24 @@ namespace AMDiS {
else else
solver = new mtl::matrix::umfpack::solver<matrix_type>(A, UMFPACK_STRATEGY_SYMMETRIC); solver = new mtl::matrix::umfpack::solver<matrix_type>(A, UMFPACK_STRATEGY_SYMMETRIC);
} else { } else {
if (!multipleRhs) if (!multipleRhs) {
if (store_symbolic) if (store_symbolic)
solver->update_numeric(); solver->update_numeric();
else else
solver->update(); solver->update();
}
} }
int code = (*solver)(x, b); int code = (*solver)(x, b);
mtl::dense_vector<value_type> r(b); if (info > 0) {
r -= A * x; mtl::dense_vector<value_type> r(b);
residual = two_norm(r); r -= A * x;
std::cout << "UmfPackSolver: ||b-Ax|| = " << residual << "\n"; residual = two_norm(r);
std::cout << "UmfPackSolver: ||b-Ax|| = " << residual << "\n";
if (residual > tolerance) {
WARNING("Tolerance tol=%e could not be reached!\n",tolerance);
}
}
return code; return code;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment