Commit e43e8013 authored by Thomas Witkowski's avatar Thomas Witkowski

SimpleResidualEstimator ready and documented.

parent 97be72e8
......@@ -92,7 +92,6 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/Element.cc
${SOURCE_DIR}/ElementData.cc
${SOURCE_DIR}/ElementDofIterator.cc
${SOURCE_DIR}/Estimator.cc
${SOURCE_DIR}/FiniteElemSpace.cc
${SOURCE_DIR}/FirstOrderAssembler.cc
${SOURCE_DIR}/FirstOrderTerm.cc
......@@ -123,12 +122,10 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/Quadrature.cc
${SOURCE_DIR}/RCNeighbourList.cc
${SOURCE_DIR}/Recovery.cc
${SOURCE_DIR}/RecoveryEstimator.cc
${SOURCE_DIR}/RefinementManager.cc
${SOURCE_DIR}/RefinementManager1d.cc
${SOURCE_DIR}/RefinementManager2d.cc
${SOURCE_DIR}/RefinementManager3d.cc
${SOURCE_DIR}/ResidualEstimator.cc
${SOURCE_DIR}/RobinBC.cc
${SOURCE_DIR}/ScalableQuadrature.cc
${SOURCE_DIR}/SecondOrderAssembler.cc
......@@ -147,6 +144,10 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc
${SOURCE_DIR}/VertexVector.cc
${SOURCE_DIR}/ZeroOrderAssembler.cc
${SOURCE_DIR}/ZeroOrderTerm.cc
${SOURCE_DIR}/est/Estimator.cc
${SOURCE_DIR}/est/RecoveryEstimator.cc
${SOURCE_DIR}/est/ResidualEstimator.cc
${SOURCE_DIR}/est/SimpleResidualEstimator.cc
${SOURCE_DIR}/io/ArhReader.cc
${SOURCE_DIR}/io/ArhWriter.cc
${SOURCE_DIR}/io/DataCollector.cc
......@@ -345,6 +346,11 @@ INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/nonlin/)
list(APPEND deb_add_dirs "include/amdis/nonlin")
FILE(GLOB HEADERS "${SOURCE_DIR}/est/*.h")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/est/)
list(APPEND deb_add_dirs "include/amdis/est")
FILE(GLOB HEADERS "${SOURCE_DIR}/time/*.h")
INSTALL(FILES ${HEADERS}
DESTINATION include/amdis/time/)
......
......@@ -59,7 +59,6 @@
#include "Element.h"
#include "ElementDofIterator.h"
#include "Error.h"
#include "Estimator.h"
#include "FiniteElemSpace.h"
#include "FirstOrderTerm.h"
#include "FixVec.h"
......@@ -112,6 +111,8 @@
#include "VertexVector.h"
#include "ZeroOrderTerm.h"
#include "est/Estimator.h"
#include "io/ArhReader.h"
#include "io/ArhWriter.h"
#include "io/FileWriter.h"
......
......@@ -12,7 +12,7 @@
#include "AdaptInstationary.h"
#include "Initfile.h"
#include "Estimator.h"
#include "est/Estimator.h"
#include "ProblemIterationInterface.h"
#include "ProblemTimeInterface.h"
#include "Serializer.h"
......
......@@ -12,7 +12,7 @@
#include "AdaptStationary.h"
#include "Initfile.h"
#include "Estimator.h"
#include "est/Estimator.h"
#include "ProblemIterationInterface.h"
#include <math.h>
......
......@@ -69,7 +69,7 @@ namespace AMDiS {
return;
}
}
ElementMatrix& mat = rememberElMat ? elementMatrix : userMat;
if (secondOrderAssembler)
......@@ -315,8 +315,8 @@ namespace AMDiS {
FUNCNAME("Assembler::matVecAssemble()");
Element *el = elInfo->getElement();
ElementVector uhOldLoc(operat->uhOld->getFeSpace() == rowFeSpace ? nRow : nCol);
ElementVector uhOldLoc(operat->uhOld->getFeSpace() == rowFeSpace ?
nRow : nCol);
operat->uhOld->getLocalVector(el, uhOldLoc);
if (el != lastMatEl) {
......
......@@ -17,14 +17,15 @@
#include "ITL_Preconditioner.h"
#include "MatrixVector.h"
#include "SystemVector.h"
#include "Estimator.h"
#include "RecoveryEstimator.h"
#include "ResidualEstimator.h"
#include "est/Estimator.h"
#include "LeafData.h"
#include "SurfaceRegion_ED.h"
#include "ElementRegion_ED.h"
#include "DOFMatrix.h"
#include "UmfPackSolver.h"
#include "est/RecoveryEstimator.h"
#include "est/ResidualEstimator.h"
#include "est/SimpleResidualEstimator.h"
#include "time/RosenbrockMethod.h"
#include "nonlin/NonLinSolver.h"
......@@ -102,6 +103,9 @@ namespace AMDiS {
creator = new ResidualEstimator::Creator;
addCreator("residual", creator);
creator = new SimpleResidualEstimator::Creator;
addCreator("simple-residual", creator);
creator = new RecoveryEstimator::Creator;
addCreator("recovery", creator);
}
......
......@@ -56,10 +56,12 @@ namespace AMDiS {
dimOfWorld = Global::getGeo(WORLD);
}
ElInfo::~ElInfo()
{}
void ElInfo::coordToWorld(const DimVec<double>& l,
WorldVector<double>& w) const
......@@ -80,12 +82,14 @@ namespace AMDiS {
}
}
double ElInfo::calcDet() const
{
testFlag(Mesh::FILL_COORDS);
return calcDet(coord);
}
double ElInfo::calcDet(const FixVec<WorldVector<double>, VERTEX> &coords) const
{
FUNCNAME("ElInfo::calcDet()");
......@@ -114,10 +118,8 @@ namespace AMDiS {
det = norm(&e1);
} else {
det = (coords[1][0] - coords[0][0]) * (coords[2][1] - coords[0][1]) -
(coords[1][1] - coords[0][1]) * (coords[2][0] - coords[0][0]);
}
break;
case 3:
......
......@@ -735,13 +735,13 @@ namespace AMDiS {
vectorProduct(elementNormal, e0, normal);
}
double det = norm(&normal);
double detn = norm(&normal);
TEST_EXIT_DBG(det > 1.e-30)("det = 0 on face %d\n", side);
TEST_EXIT_DBG(detn > 1.e-30)("det = 0 on face %d\n", side);
normal *= 1.0 / det;
normal *= 1.0 / detn;
return det;
return detn;
}
......@@ -762,13 +762,13 @@ namespace AMDiS {
vectorProduct(e0, e1, elementNormal);
double det = norm(&elementNormal);
double detn = norm(&elementNormal);
TEST_EXIT_DBG(det > 1.e-30)("det = 0");
TEST_EXIT_DBG(detn > 1.e-30)("det = 0");
elementNormal *= 1.0 / det;
elementNormal *= 1.0 / detn;
return det;
return detn;
}
......
......@@ -16,8 +16,8 @@
#include "ProblemInstat.h"
#include "AdaptStationary.h"
#include "AdaptInstationary.h"
#include "Estimator.h"
#include "StandardProblemIteration.h"
#include "est/Estimator.h"
#include "io/FileWriter.h"
namespace AMDiS {
......
......@@ -14,14 +14,12 @@
#include <boost/lexical_cast.hpp>
#include "ProblemStat.h"
#include "RecoveryEstimator.h"
#include "Serializer.h"
#include "AbstractFunction.h"
#include "Operator.h"
#include "SystemVector.h"
#include "DOFMatrix.h"
#include "FiniteElemSpace.h"
#include "Estimator.h"
#include "Marker.h"
#include "AdaptInfo.h"
#include "io/FileWriter.h"
......@@ -35,6 +33,7 @@
#include "PeriodicBC.h"
#include "Lagrange.h"
#include "Flag.h"
#include "est/Estimator.h"
#include "io/VtkWriter.h"
#include "io/ValueReader.h"
#include "ProblemStatDbg.h"
......@@ -790,6 +789,8 @@ namespace AMDiS {
if (matrix)
nnz += matrix->getBaseMatrix().nnz();
}
// And now assemble boundary conditions on the vectors
assembleBoundaryConditions(rhs->getDOFVector(i),
......
......@@ -11,11 +11,12 @@
#include "RobinBC.h"
#include "Estimator.h"
#include "Assembler.h"
#include "DOFVector.h"
#include "DOFMatrix.h"
#include "SurfaceOperator.h"
#include "est/Estimator.h"
#include <math.h>
namespace AMDiS {
......
......@@ -10,8 +10,8 @@
// See also license.opensource.txt in the distribution.
#include "Estimator.h"
#include "Assembler.h"
#include "est/Estimator.h"
template<typename T>
void RobinBC<T>::fillLocalBC(DOFVector<T>* vector,
......
......@@ -77,9 +77,9 @@ namespace AMDiS {
newAssembler = new Stand2(op, assembler, quad);
} else {
if (pwConst) {
newAssembler = new Pre2(op, assembler, quad);
newAssembler = new Pre2(op, assembler, quad);
} else {
newAssembler = new Quad2(op, assembler, quad);
newAssembler = new Quad2(op, assembler, quad);
}
}
......@@ -330,7 +330,7 @@ namespace AMDiS {
for (int i = 0; i < nRow; i++) {
(*(psi->getGrdPhi(i)))(quadrature->getLambda(iq), grdPsi);
for (int j = 0; j < nCol; j++) {
tmpVec = (LALt[iq] * grdPhi[j]);
tmpVec = (LALt[iq] * grdPhi[j]);
mat[i][j] += quadrature->getWeight(iq) * dot(grdPsi, tmpVec);
}
}
......
......@@ -132,7 +132,8 @@ namespace AMDiS {
}
/// Implements SecondOrderTerm::getLALt().
inline void getLALt(const ElInfo *elInfo, vector<mtl::dense2D<double> > &LALt) const
inline void getLALt(const ElInfo *elInfo,
vector<mtl::dense2D<double> > &LALt) const
{
const DimVec<WorldVector<double> > &grdLambda = elInfo->getGrdLambda();
const int nPoints = static_cast<int>(LALt.size());
......
......@@ -52,16 +52,16 @@ namespace AMDiS {
}
const FixVec<int, WORLD>& Triangle::sortFaceIndices(int face,
FixVec<int,WORLD> *vec) const
FixVec<int, WORLD> *vec) const
{
static MatrixOfFixVecs<FixVec<int,WORLD> > *sorted_2d = NULL;
static MatrixOfFixVecs<FixVec<int, WORLD> > *sorted_2d = NULL;
int no = 0;
FixVec<int,WORLD> *val = NULL;
FixVec<int, WORLD> *val = NULL;
const int *vof = vertexOfEdge[face];
if (NULL == sorted_2d) {
sorted_2d = new MatrixOfFixVecs<FixVec<int,WORLD> >(2, 3, 2, NO_INIT);
sorted_2d = new MatrixOfFixVecs<FixVec<int, WORLD> >(2, 3, 2, NO_INIT);
(*sorted_2d)[1][0][1] = (*sorted_2d)[1][1][0] =
(*sorted_2d)[2][0][0] = (*sorted_2d)[2][1][1] = 0;
......@@ -83,7 +83,7 @@ namespace AMDiS {
val = &((*sorted_2d)[face][no]);
}
return *(const_cast<const FixVec<int,WORLD>* >(val));
return *(const_cast<const FixVec<int, WORLD>* >(val));
}
......
......@@ -95,7 +95,7 @@ namespace AMDiS {
bool hasSide(Element* sideElem) const;
/// implements Element::sortFaceIndices
const FixVec<int,WORLD>& sortFaceIndices(int face, FixVec<int,WORLD> *vec) const;
const FixVec<int, WORLD>& sortFaceIndices(int face, FixVec<int, WORLD> *vec) const;
/// implements Element::isLine. Returns false because this element is a Triangle
inline bool isLine() const
......
......@@ -322,7 +322,7 @@ namespace AMDiS {
}
if (D2uhqp == NULL && degree > 2 && (*it)->secondOrderTerms()) {
D2uhqp = new WorldMatrix<double>[nPoints];
uh[system]->getD2AtQPs(elInfo, NULL, quadFast[system], D2uhqp);
uh[system]->getD2AtQPs(elInfo, NULL, quadFast[system], D2uhqp);
}
}
}
......@@ -533,11 +533,13 @@ namespace AMDiS {
if (factor) {
if (D2UhIq)
(*it)->evalSecondOrder(nPoints, uhIq, grdUhIq, D2UhIq, result, -factor);
(*it)->evalSecondOrder(nPoints, uhIq, grdUhIq, D2UhIq, result, -factor);
if (grdUhIq) {
(*it)->evalFirstOrderGrdPsi(nPoints, uhIq, grdUhIq, D2UhIq, result, factor);
(*it)->evalFirstOrderGrdPhi(nPoints, uhIq, grdUhIq, D2UhIq, result, factor);
(*it)->evalFirstOrderGrdPsi(nPoints, uhIq, grdUhIq, D2UhIq,
result, factor);
(*it)->evalFirstOrderGrdPhi(nPoints, uhIq, grdUhIq, D2UhIq,
result, factor);
}
if (num_rows(uhIq) > 0)
......
......@@ -59,7 +59,7 @@ namespace AMDiS {
* \ingroup Estimator
*
* \brief
* Estimator for scalar problems.
* Residual estimator.
*/
class ResidualEstimator : public Estimator
{
......@@ -88,8 +88,8 @@ namespace AMDiS {
virtual void init(double timestep);
/** \brief
* Estimates the error on an element. For more information about the parameter,
* see the description \ref Estimator::estimateElement.
* Estimates the error on an element. For more information about the
* parameter, see the description \ref Estimator::estimateElement.
*/
virtual void estimateElement(ElInfo *elInfo, DualElInfo *dualElInfo = NULL);
......
//
// Software License for AMDiS
//
// Copyright (c) 2010 Dresden University of Technology
// All rights reserved.
// Authors: Simon Vey, Thomas Witkowski et al.
//
// This file is part of AMDiS
//
// See also license.opensource.txt in the distribution.
#include "est/SimpleResidualEstimator.h"
#include "Operator.h"
#include "DOFMatrix.h"
#include "DOFVector.h"
#include "Assembler.h"
#include "Traverse.h"
#include "Initfile.h"
namespace AMDiS {
SimpleResidualEstimator::SimpleResidualEstimator(std::string name)
: Estimator(name, 0),
C0(0.0),
C1(0.0)
{
FUNCNAME("SimpleResidualEstimator::SimpleResidualEstimator()");
// === Read parameters C0 and C1 from init file. ===
Parameters::get(name + "->C0", C0);
Parameters::get(name + "->C1", C1);
C0 = C0 > 1.e-25 ? sqr(C0) : 0.0;
C1 = C1 > 1.e-25 ? sqr(C1) : 0.0;
}
void SimpleResidualEstimator::init(double)
{
FUNCNAME("SimpleResidualEstimator::init()");
// === Create data structures. ===
basFcts = uh[0]->getFeSpace()->getBasisFcts();
dim = mesh->getDim();
degree = basFcts->getDegree() * 2;
quad = Quadrature::provideQuadrature(dim, degree);
nPoints = quad->getNumPoints();
Flag flag = INIT_PHI;
if (degree > 2)
flag |= INIT_D2_PHI;
quadFast = FastQuadrature::provideFastQuadrature(basFcts, *quad, flag);
uhEl.change_dim(basFcts->getNumber());
uhNeigh.change_dim(basFcts->getNumber());
riq.change_dim(nPoints);
D2uhqp = NULL;
// === Clear error indicators and mark elements for jumpRes. ===
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
while (elInfo) {
elInfo->getElement()->setEstimation(0.0, 0);
elInfo->getElement()->setMark(1);
elInfo = stack.traverseNext(elInfo);
}
est_sum = 0.0;
est_max = 0.0;
traverseFlag =
Mesh::FILL_NEIGH |
Mesh::FILL_COORDS |
Mesh::FILL_OPP_COORDS |
Mesh::FILL_BOUND |
Mesh::FILL_GRD_LAMBDA |
Mesh::FILL_DET |
Mesh::CALL_LEAF_EL;
neighInfo = mesh->createNewElInfo();
// === Prepare date for computing jump residual. ===
if (C1 > 0.0 && dim > 1) {
surfaceQuad = Quadrature::provideQuadrature(dim - 1, degree);
nPointsSurface = surfaceQuad->getNumPoints();
grdUhEl.resize(nPointsSurface);
grdUhNeigh.resize(nPointsSurface);
jump.resize(nPointsSurface);
localJump.resize(nPointsSurface);
nNeighbours = Global::getGeo(NEIGH, dim);
lambdaNeigh = new DimVec<WorldVector<double> >(dim, NO_INIT);
lambda = new DimVec<double>(dim, NO_INIT);
}
}
void SimpleResidualEstimator::exit(bool output)
{
FUNCNAME("SimpleResidualEstimator::exit()");
// === Calculate the root of the estimations and make output. ===
est_sum = sqrt(est_sum);
if (output)
MSG("estimate = %.8e\n", est_sum);
/// === Delete data structures. ===
if (D2uhqp != NULL)
delete [] D2uhqp;
if (C1 && (dim > 1)) {
delete lambdaNeigh;
delete lambda;
}
delete neighInfo;
}
void SimpleResidualEstimator::estimateElement(ElInfo *elInfo, DualElInfo *)
{
FUNCNAME("SimpleResidualEstimator::estimateElement()");
TEST_EXIT(matrix[0])("Should not happen!\n");
// Get pointer to element object.
Element *el = elInfo->getElement();
// Get error estimation of this element.
double est_el = el->getEstimation(0);
// Shortcut for the system matrix.
DOFMatrix *dofMat = const_cast<DOFMatrix*>(matrix[0]);
// Shortcut for the right hand side DOF vector
DOFVector<double> *dofVec = const_cast<DOFVector<double>*>(fh[0]);
// === Init assembler ===
std::vector<Operator*>::iterator it;
std::vector<double*>::iterator itfac;
// Matrix assembler are only initialized with the corresponding multiply
// factors are != 0
for (it = dofMat->getOperatorsBegin(), itfac = dofMat->getOperatorEstFactorBegin();
it != dofMat->getOperatorsEnd(); ++it, ++itfac)
if (*itfac == NULL || **itfac != 0.0)
(*it)->getAssembler()->initElement(elInfo, NULL, quad);
// Vector assembler are only initialized if C0 is set. Note that the jump
// residual (thus C1) does not contain the right hand side.
if (C0 > 0.0)
for (it = dofVec->getOperatorsBegin(); it != dofVec->getOperatorsEnd(); ++it)
(*it)->getAssembler()->initElement(elInfo, NULL, quad);
// === Compute element residuals and time error estimation. ===
if (C0 > 0.0)
est_el += computeElementResidual(elInfo);
// === Compute jump residuals. ===
if (C1 > 0.0 && dim > 1)
est_el += computeJumpResidual(elInfo);
// === Update global residual variables. ===
el->setEstimation(est_el, 0);
el->setMark(0);
est_sum += est_el;
est_max = std::max(est_max, est_el);
}
double SimpleResidualEstimator::computeElementResidual(ElInfo *elInfo)
{
FUNCNAME("SimpleResidualEstimator::computeElementResidual()");
double det = elInfo->getDet();
double h2 = h2_from_det(det, dim);
riq = 0.0;
DOFMatrix *dofMat = const_cast<DOFMatrix*>(matrix[0]);
DOFVector<double> *dofVec = const_cast<DOFVector<double>*>(fh[0]);
// === If there is a valid left hand side operator get the solution ===
// === vector or its derivations on the quadrature points of the ===
// === element. ===
std::vector<Operator*>::iterator it;
std::vector<double*>::iterator itfac;
for (it = dofMat->getOperatorsBegin(), itfac = dofMat->getOperatorEstFactorBegin();
it != dofMat->getOperatorsEnd(); ++it, ++itfac) {
if (*itfac == NULL || **itfac != 0.0) {
if (num_rows(uhQP) == 0 && (*it)->zeroOrderTerms()) {
uhQP.change_dim(nPoints);
uh[0]->getVecAtQPs(elInfo, NULL, quadFast, uhQP);
}
if (D2uhqp == NULL && degree > 2 && (*it)->secondOrderTerms()) {
D2uhqp = new WorldMatrix<double>[nPoints];
uh[0]->getD2AtQPs(elInfo, NULL, quadFast, D2uhqp);
}
}
}
// === Compute the element residual and store it in irq. ===
r(elInfo, nPoints, uhQP, D2uhqp, dofMat, dofVec, quad, riq);
// === Add integral over r square. ===
double result = 0.0;
for (int iq = 0; iq < nPoints; iq++)
result += quad->getWeight(iq) * riq[iq] * riq[iq];
if (norm == NO_NORM || norm == L2_NORM)
result = C0 * h2 * h2 * det * result;
else
result = C0 * h2 * det * result;
return result;
}
double SimpleResidualEstimator::computeJumpResidual(ElInfo *elInfo)
{
FUNCNAME("SimpleResidualEstimator::computeJumpResidual()");
// === Init temporary variables. ===
double result = 0.0;
int dow = Global::getGeo(WORLD);
Element *el = elInfo->getElement();
const DimVec<WorldVector<double> > &grdLambda = elInfo->getGrdLambda();
double det = elInfo->getDet();
double h2 = h2_from_det(det, dim);
/// === Compute jump on all faces of the current element. ===
for (int face = 0; face < nNeighbours; face++) {
// Pointer to neighbouring element.
Element *neigh = const_cast<Element*>(elInfo->getNeighbour(face));