From 5de011fba6b61d425ccae66cc567354e6cf46e2e Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Tue, 21 Dec 2010 22:46:47 +0000 Subject: [PATCH] RecoveryEstimator modified to have a structure similar to ResidualEstimator --- AMDiS/src/ProblemVec.cc | 4 +- AMDiS/src/RecoveryEstimator.cc | 154 ++++++++++++++++++--------------- AMDiS/src/RecoveryEstimator.h | 42 +++++++-- AMDiS/src/UmfPackSolver.h | 19 ++-- 4 files changed, 135 insertions(+), 84 deletions(-) diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc index dca63831..41403824 100644 --- a/AMDiS/src/ProblemVec.cc +++ b/AMDiS/src/ProblemVec.cc @@ -772,12 +772,12 @@ namespace AMDiS { assembleFlag); } - if (asmMatrix) { +// if (asmMatrix) { solverMatrix.setMatrix(*systemMatrix); createPrecon(); INFO(info, 8)("fillin of assembled matrix: %d\n", nnz); - } +// } #ifdef _OPENMP INFO(info, 8)("buildAfterCoarsen needed %.5f seconds system time / %.5f seconds wallclock time\n", diff --git a/AMDiS/src/RecoveryEstimator.cc b/AMDiS/src/RecoveryEstimator.cc index 501ee0a2..67cde50d 100644 --- a/AMDiS/src/RecoveryEstimator.cc +++ b/AMDiS/src/RecoveryEstimator.cc @@ -15,12 +15,13 @@ 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), - uh_(uh), - relative_(0), + uh(uh_), + relative(0), C(1.0), method(0), + addEstimationToOld(false), feSpace(NULL), f_vec(NULL), f_scal(NULL), @@ -29,14 +30,14 @@ namespace AMDiS { { FUNCNAME("RecoveryEstimator::constructor()"); - GET_PARAMETER(0, name + "->rec method", "%d", &method); - GET_PARAMETER(0, name + "->rel error", "%d", &relative_); + GET_PARAMETER(0, name + "->rec method", "%d", &method); // 0, 1, or 2 (see Recovery.h) + GET_PARAMETER(0, name + "->rel error", "%d", &relative); // 0 or 1 GET_PARAMETER(0, name + "->C", "%f", &C); C = C > 1e-25 ? sqr(C) : 1.0; if (norm == H1_NORM) { - feSpace = uh->getFeSpace(); + feSpace = uh_->getFeSpace(); degree = feSpace->getBasisFcts()->getDegree(); if (degree <= 2 && C != 1.0) { @@ -44,10 +45,10 @@ namespace AMDiS { WAIT; } } else { - degree = uh->getFeSpace()->getBasisFcts()->getDegree() + 1; + degree = uh_->getFeSpace()->getBasisFcts()->getDegree() + 1; feSpace = FiniteElemSpace::provideFeSpace(NULL, - Lagrange::getLagrange(uh->getFeSpace()->getMesh()->getDim(), degree), - uh->getFeSpace()->getMesh(), + Lagrange::getLagrange(uh_->getFeSpace()->getMesh()->getDim(), degree), + uh_->getFeSpace()->getMesh(), name + "->feSpace"); if (method == 2) { @@ -66,72 +67,114 @@ namespace AMDiS { rec_struct = new Recovery(norm, method); } - - double RecoveryEstimator::estimate(double timestep) + void RecoveryEstimator::init(double ts) { - FUNCNAME("RecoveryEstimator::estimate()"); - - const BasisFunction *basFcts = uh_->getFeSpace()->getBasisFcts(); - Mesh *mesh = uh_->getFeSpace()->getMesh(); + FUNCNAME("RecoveryEstimator::init()"); + + basFcts = uh->getFeSpace()->getBasisFcts(); int dim = mesh->getDim(); - int dow = Global::getGeo(WORLD); - double h1Norm2 = 0.0; - + h1Norm2 = 0.0; + if (norm == H1_NORM) { // sets recovery gradient. 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 - 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(); } 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(); } int deg = 2 * std::max(basFcts->getDegree(), rec_basFcts->getDegree()); - Quadrature *quad = Quadrature::provideQuadrature(dim, deg); - int nPoints = quad->getNumPoints(); + quad = Quadrature::provideQuadrature(dim, deg); + nPoints = quad->getNumPoints(); - WorldVector<double> quad_pt; - WorldVector<double> *grdAtQP = new WorldVector<double>[nPoints]; +// WorldVector<double> quad_pt; + grdAtQP = new WorldVector<double>[nPoints]; - mtl::dense_vector<WorldVector<double> > recoveryGrdAtQP(nPoints); - mtl::dense_vector<double> uhAtQP(nPoints), recoveryUhAtQP(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); + recoveryGrdAtQP = mtl::dense_vector<WorldVector<double> >(nPoints); + uhAtQP = mtl::dense_vector<double>(nPoints); + recoveryUhAtQP = mtl::dense_vector<double>(nPoints); + 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 + if(!addEstimationToOld) { TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); while (elInfo) { elInfo->getElement()->setEstimation(0.0, row); 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 - est_sum = est_max = est_t_sum = 0.0; + MPI::COMM_WORLD.Allreduce(&send_est_sum, &est_sum, 1, MPI_DOUBLE, MPI_SUM); + 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, - Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | - Mesh::FILL_DET | Mesh::FILL_GRD_LAMBDA); - while (elInfo) { + if (output) { + MSG("estimate for component %d = %.8e\n", row, est_sum); + } + } + + void RecoveryEstimator::estimateElement(ElInfo *elInfo, DualElInfo *dualElInfo) + { + FUNCNAME("RecoveryEstimator::estimateElement()"); + Element *el = elInfo->getElement(); double det = elInfo->getDet(); double errEl = 0.0; + double estEl = el->getEstimation(row); + int dow = Global::getGeo(WORLD); if (norm == H1_NORM) { // 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); if (f_scal) { if (aux_vec) aux_vec->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP); else - uh_->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP); + uh->getVecAtQPs(elInfo, NULL, quadFast, uhAtQP); } // calc h1 error @@ -151,7 +194,7 @@ namespace AMDiS { } } else { // 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); // calc l2 error @@ -159,12 +202,12 @@ namespace AMDiS { errEl += quad->getWeight(i) * sqr(recoveryUhAtQP[i] - uhAtQP[i]); } - double estEl = C * det * errEl; + estEl += C * det * errEl; el->setEstimation(estEl, row); est_sum += estEl; est_max = std::max(est_max, estEl); - if (relative_) { + if (relative) { double normEl = 0.0; if (norm == H1_NORM) { @@ -181,31 +224,6 @@ namespace AMDiS { 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; } } diff --git a/AMDiS/src/RecoveryEstimator.h b/AMDiS/src/RecoveryEstimator.h index 636c37b8..218a484a 100644 --- a/AMDiS/src/RecoveryEstimator.h +++ b/AMDiS/src/RecoveryEstimator.h @@ -59,19 +59,24 @@ namespace AMDiS { }; /// constructor - RecoveryEstimator(std::string name, DOFVector<double> *uh, int r = -1); + RecoveryEstimator(std::string name, DOFVector<double> *uh_, int r = -1); /// destructor. virtual ~RecoveryEstimator() {} - /// implements \ref Estimator::estimate(). - virtual double estimate(double timestep = 0.0); + /// implements \ref Estimator::init(double). + 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. - inline void setUh(DOFVector<double> *uh) + inline void setUh(DOFVector<double> *uh_) { - uh_ = uh; + uh = uh_; } /// Sets f. @@ -92,6 +97,10 @@ namespace AMDiS { aux_vec = uh; } + inline void setAddEstimationToOld(bool value) + { + addEstimationToOld = value; + } /// Gets recovery gradient. inline DOFVector<WorldVector<double> >* getRecGrd() @@ -108,10 +117,10 @@ namespace AMDiS { protected: /// finite element solution - DOFVector<double> *uh_; + DOFVector<double> *uh; /// absolute or relative error? - int relative_; + int relative; /// constant for scaling the estimator double C; @@ -119,6 +128,8 @@ namespace AMDiS { /// recovery method int method; + bool addEstimationToOld; + /// Working finite element space const FiniteElemSpace *feSpace; @@ -143,6 +154,23 @@ namespace AMDiS { /// Recovery structure. 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; }; } diff --git a/AMDiS/src/UmfPackSolver.h b/AMDiS/src/UmfPackSolver.h index c8f6e5ed..25906f4a 100644 --- a/AMDiS/src/UmfPackSolver.h +++ b/AMDiS/src/UmfPackSolver.h @@ -87,19 +87,24 @@ namespace AMDiS { else solver = new mtl::matrix::umfpack::solver<matrix_type>(A, UMFPACK_STRATEGY_SYMMETRIC); } else { - if (!multipleRhs) + if (!multipleRhs) { if (store_symbolic) solver->update_numeric(); else - solver->update(); + solver->update(); + } } int code = (*solver)(x, b); - mtl::dense_vector<value_type> r(b); - r -= A * x; - residual = two_norm(r); - std::cout << "UmfPackSolver: ||b-Ax|| = " << residual << "\n"; - + if (info > 0) { + mtl::dense_vector<value_type> r(b); + r -= A * x; + 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; } -- GitLab