From 8e4f16acba7035befdf99b18fd902274ab544b4b Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Fri, 12 Aug 2011 08:12:40 +0000 Subject: [PATCH] CouplingIterationInterface created, similar to CouplingTimeInterface --- AMDiS/src/AMDiS.h | 4 +- AMDiS/src/AMDiS_fwd.h | 1 + AMDiS/src/CouplingIterationInterface.cc | 123 ++++++++++++++++++++++++ AMDiS/src/CouplingIterationInterface.h | 90 +++++++++++++++++ AMDiS/src/CouplingTimeInterface.h | 6 ++ AMDiS/src/CreatorMap.cc | 1 + AMDiS/src/DOFVector.cc | 93 ++++++++++++++++++ AMDiS/src/DOFVector.h | 11 +++ AMDiS/src/ITL_OEMSolver.hh | 10 +- AMDiS/src/MTL4Solver.h | 5 + AMDiS/src/ProblemStat.cc | 9 ++ 11 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 AMDiS/src/CouplingIterationInterface.cc create mode 100644 AMDiS/src/CouplingIterationInterface.h diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h index fae091ce..82b62be9 100644 --- a/AMDiS/src/AMDiS.h +++ b/AMDiS/src/AMDiS.h @@ -39,6 +39,8 @@ #include "CoarseningManager1d.h" #include "CoarseningManager2d.h" #include "CoarseningManager3d.h" +#include "CouplingTimeInterface.h" +#include "CouplingIterationInterface.h" #include "CreatorInterface.h" #include "CreatorMap.h" #include "Debug.h" @@ -63,7 +65,7 @@ #include "FixVec.h" #include "Flag.h" #include "Global.h" -#include "Initfile.h" // replacement for Parameters.h +#include "Initfile.h" #include "ITL_Preconditioner.h" #include "ITL_Solver.h" #include "Lagrange.h" diff --git a/AMDiS/src/AMDiS_fwd.h b/AMDiS/src/AMDiS_fwd.h index a1070295..e3b96b80 100644 --- a/AMDiS/src/AMDiS_fwd.h +++ b/AMDiS/src/AMDiS_fwd.h @@ -35,6 +35,7 @@ namespace AMDiS { class BoundaryManager; class CGSolver; class CoarseningManager; + class CouplingIterationInterface; class DiagonalPreconditioner; class DOFAdmin; class DOFContainer; diff --git a/AMDiS/src/CouplingIterationInterface.cc b/AMDiS/src/CouplingIterationInterface.cc new file mode 100644 index 00000000..1f609e47 --- /dev/null +++ b/AMDiS/src/CouplingIterationInterface.cc @@ -0,0 +1,123 @@ +// ============================================================================ +// == == +// == AMDiS - Adaptive multidimensional simulations == +// == == +// == http://www.amdis-fem.org == +// == == +// ============================================================================ +// +// 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. + + + +/** \file CouplingIterationInterface.h */ + +#include "Flag.h" +#include "CouplingIterationInterface.h" + +namespace AMDiS { + + /// add problem by number + void CouplingIterationInterface::addIterationInterface(ProblemIterationInterface* probIter, int number) + { + unsigned idx = std::min(problems.size(), static_cast<unsigned>(number)); + if (number < 0) + idx = problems.size(); + std::vector<ProblemIterationInterface*>::iterator pos = problems.begin() + idx; + + problems.insert(pos, probIter); + }; + + + /// Called before each adaption loop iteration. + void CouplingIterationInterface::beginIteration(AdaptInfo *adaptInfo) + { FUNCNAME("CouplingIterationInterface::beginIteration()"); + MSG("\n"); + MSG("begin of iteration number: %d/%d\n", + adaptInfo->getTimestepNumber() + 1, + adaptInfo->getNumberOfTimesteps()); + MSG("==================================================\n"); + }; + + + /** \brief + * Determines the execution order of the single adaption steps. If adapt is + * true, mesh adaption will be performed. This allows to avoid mesh adaption, + * e.g. in timestep adaption loops of timestep adaptive strategies. + */ + Flag CouplingIterationInterface::oneIteration(AdaptInfo *adaptInfo, Flag toDo) + { FUNCNAME("CouplingIterationInterface::oneIteration()"); + Flag flag = 0; + + for (unsigned i = 0; i < problems.size(); ++i) { + problems[i]->beginIteration(adaptInfo); + flag |= problems[i]->oneIteration(adaptInfo, toDo); + problems[i]->endIteration(adaptInfo); + } + + return flag; + }; + + + /// Called after each adaption loop iteration. + void CouplingIterationInterface::endIteration(AdaptInfo *adaptInfo) + { FUNCNAME("CouplingIterationInterface::endIteration()"); + MSG("\n"); + MSG("end of iteration number: %d\n", + adaptInfo->getTimestepNumber() + 1); + MSG("==================================================\n"); + }; + + + /// Returns number of managed problems + int CouplingIterationInterface::getNumProblems() + { + int num= 0; + for (unsigned i = 0; i < problems.size(); ++i) + num += problems[i]->getNumProblems(); + return num; + }; + + + /** \brief + * Returns the problem with the given number. If only one problem + * is managed by this master problem, the number hasn't to be given. + */ + ProblemStatBase *CouplingIterationInterface::getProblem(int number) + { + int maxNum = getNumProblems(); + if (maxNum <= number || number < 0) + throw(std::runtime_error("Problem number out of range.")); + + int sum = 0; + ProblemStatBase *probIter = NULL; + for (unsigned i = 0; i < problems.size(); ++i) { + if (sum + problems[i]->getNumProblems() <= number) + sum += problems[i]->getNumProblems(); + else + probIter = problems[i]->getProblem(number - sum); + } + if (probIter == NULL) + throw(std::runtime_error("Problem not found. Should not happen, since number is in range.")); + return probIter; + }; + + + /// Returns the name of the problem. + std::string CouplingIterationInterface::getName(int number) + { + if (static_cast<int>(problems.size()) <= number || number < 0) + throw(std::runtime_error("Problem number out of range.")); + + return problems[number]->getName(); + }; + +} // namespace AMDiS diff --git a/AMDiS/src/CouplingIterationInterface.h b/AMDiS/src/CouplingIterationInterface.h new file mode 100644 index 00000000..39c4e9df --- /dev/null +++ b/AMDiS/src/CouplingIterationInterface.h @@ -0,0 +1,90 @@ +// ============================================================================ +// == == +// == AMDiS - Adaptive multidimensional simulations == +// == == +// == http://www.amdis-fem.org == +// == == +// ============================================================================ +// +// 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. + + + +/** \file CouplingIterationInterface.h */ + +#ifndef AMDIS_COUPLINGITERATIONINTERFACE_H +#define AMDIS_COUPLINGITERATIONINTERFACE_H + +#include "Flag.h" +#include "AdaptInfo.h" +#include "ProblemIterationInterface.h" + +namespace AMDiS { + + /** \brief + * Interface for master problems needed by the adaption loop. A master problem + * can handle one single or multiple coupled problems. In the latter case, + * the master problem can determine the execution order of the build, solve, + * estimate, and adapt steps of the single problems in \ref oneIteration(). + * Standard execution order depends on the ordering of the problems in the + * problem-list, that is filled by addProblem. Alternatively one can a access + * each problem by an unique name. + */ + class CouplingIterationInterface : public ProblemIterationInterface + { + public: + virtual ~CouplingIterationInterface() {} + + /// add problem by number + virtual void addIterationInterface(ProblemIterationInterface* probIter, int number = -1); + + /// Called before each adaption loop iteration. + virtual void beginIteration(AdaptInfo *adaptInfo); + + /** \brief + * Determines the execution order of the single adaption steps. If adapt is + * true, mesh adaption will be performed. This allows to avoid mesh adaption, + * e.g. in timestep adaption loops of timestep adaptive strategies. + */ + virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION); + + /// Called after each adaption loop iteration. + virtual void endIteration(AdaptInfo *adaptInfo); + + /// Returns number of managed problems + virtual int getNumProblems(); + + /** \brief + * Returns the problem with the given number. If only one problem + * is managed by this master problem, the number hasn't to be given. + */ + virtual ProblemStatBase *getProblem(int number = 0); + + /// Returns the name of the problem with the given number. + virtual std::string getName(int number); + virtual std::string getName() { return getName(0); } + + /// Function that serializes the problem plus information about the iteration. + virtual void serialize(std::ostream &out) {}; + + /// Function that deserializes the problem plus information about the iteration. + virtual void deserialize(std::istream &in) {}; + + protected: + + /// vector/map of coupled stationary problems + std::vector<ProblemIterationInterface*> problems; + }; + +} + +#endif // AMDIS_COUPLINGITERATIONINTERFACE_H + diff --git a/AMDiS/src/CouplingTimeInterface.h b/AMDiS/src/CouplingTimeInterface.h index 4eeb3374..ec89be4e 100644 --- a/AMDiS/src/CouplingTimeInterface.h +++ b/AMDiS/src/CouplingTimeInterface.h @@ -82,6 +82,12 @@ namespace AMDiS { interfaces_[i]->transferInitialSolution(adaptInfo); } + /// Function that serializes the problem plus information about the iteration. + virtual void serialize(std::ostream &out) {}; + + /// Function that deserializes the problem plus information about the iteration. + virtual void deserialize(std::istream &in) {}; + protected: /// vector of coupled time interfaces std::vector<ProblemTimeInterface*> interfaces_; diff --git a/AMDiS/src/CreatorMap.cc b/AMDiS/src/CreatorMap.cc index d21ba5c1..830a1321 100644 --- a/AMDiS/src/CreatorMap.cc +++ b/AMDiS/src/CreatorMap.cc @@ -149,5 +149,6 @@ namespace AMDiS { void CreatorMap<NonLinSolver>::addDefaultCreators() { addCreator("newton", new Newton::Creator); + addCreator("newtonArmijo", new NewtonArmijo::Creator); } } diff --git a/AMDiS/src/DOFVector.cc b/AMDiS/src/DOFVector.cc index 001cf56c..0d390f63 100644 --- a/AMDiS/src/DOFVector.cc +++ b/AMDiS/src/DOFVector.cc @@ -67,6 +67,99 @@ namespace AMDiS { } + template<> + const double& DOFVector<double>::evalAtPoint(WorldVector<double> &p, ElInfo *oldElInfo, double* values) const + { + FUNCNAME("DOFVector<double>::evalAtCoords()"); + + Mesh *mesh = feSpace->getMesh(); + const BasisFunction *basFcts = feSpace->getBasisFcts(); + + int dim = mesh->getDim(); + int nBasFcts = basFcts->getNumber(); + + DegreeOfFreedom *localIndices = new DegreeOfFreedom[nBasFcts]; + DimVec<double> lambda(dim, NO_INIT); + + ElInfo *elInfo = mesh->createNewElInfo(); + double value = 0.0; + bool inside = false; + + if (oldElInfo && oldElInfo->getMacroElement()) { + inside = mesh->findElInfoAtPoint(p, elInfo, lambda, oldElInfo->getMacroElement(), NULL, NULL); + delete oldElInfo; + } else + inside = mesh->findElInfoAtPoint(p, elInfo, lambda, NULL, NULL, NULL); + + if (oldElInfo) + oldElInfo = elInfo; + + if (inside) { + basFcts->getLocalIndices(elInfo->getElement(), feSpace->getAdmin(), localIndices); + ElementVector uh(lambda.size()); + for (int i = 0; i < lambda.size(); i++) + uh[i] = operator[](localIndices[i]); + value = basFcts->evalUh(lambda, uh); + } else + throw(std::runtime_error("Can not eval DOFVector at point p, because point is outside geometry.")); + + delete [] localIndices; + if (oldElInfo == NULL) + delete elInfo; + + if (values != NULL) + *values = value; + return value; + }; + + + template<> + const WorldVector<double>& DOFVector<WorldVector<double> >::evalAtPoint(WorldVector<double> &p, ElInfo *oldElInfo, WorldVector<double>* values) const + { + FUNCNAME("DOFVector<double>::evalAtCoords()"); + + Mesh *mesh = feSpace->getMesh(); + const BasisFunction *basFcts = feSpace->getBasisFcts(); + + int dim = mesh->getDim(); + int nBasFcts = basFcts->getNumber(); + + DegreeOfFreedom *localIndices = new DegreeOfFreedom[nBasFcts]; + DimVec<double> lambda(dim, NO_INIT); + + ElInfo *elInfo = mesh->createNewElInfo(); + + static WorldVector<double> Values(DEFAULT_VALUE, 0.0); + WorldVector<double> *val = (NULL != values) ? values : &Values; + + bool inside = false; + + if (oldElInfo && oldElInfo->getMacroElement()) { + inside = mesh->findElInfoAtPoint(p, elInfo, lambda, oldElInfo->getMacroElement(), NULL, NULL); + delete oldElInfo; + } else + inside = mesh->findElInfoAtPoint(p, elInfo, lambda, NULL, NULL, NULL); + + if (oldElInfo) + oldElInfo = elInfo; + + if (inside) { + basFcts->getLocalIndices(elInfo->getElement(), feSpace->getAdmin(), localIndices); + mtl::dense_vector<WorldVector<double> > uh(lambda.size()); + for (int i = 0; i < lambda.size(); i++) + uh[i] = operator[](localIndices[i]); + basFcts->evalUh(lambda, uh, val); + } else + throw(std::runtime_error("Can not eval DOFVector at point p, because point is outside geometry.")); + + delete [] localIndices; + if (oldElInfo == NULL) + delete elInfo; + + return ((*val)); + }; + + template<> DOFVector<WorldVector<double> >* DOFVector<double>::getGradient(DOFVector<WorldVector<double> > *grad) const diff --git a/AMDiS/src/DOFVector.h b/AMDiS/src/DOFVector.h index 9488d148..e8e28eb3 100644 --- a/AMDiS/src/DOFVector.h +++ b/AMDiS/src/DOFVector.h @@ -539,6 +539,11 @@ namespace AMDiS { void interpol(DOFVector<T> *v, double factor = 1.0); + + /// eval DOFVector at given point p. If oldElInfo != NULL the search for the element, where p is inside, + /// starts from oldElInfo. + const T& evalAtPoint(WorldVector<double> &p, ElInfo *oldElInfo = NULL, T* value = NULL) const; + /// Writes the data of the DOFVector to an output stream. void serialize(std::ostream &out) { @@ -577,6 +582,12 @@ namespace AMDiS { }; + template<> + const double& DOFVector<double>::evalAtPoint(WorldVector<double> &p, ElInfo *oldElInfo, double* value) const; + + template<> + const WorldVector<double>& DOFVector<WorldVector<double> >::evalAtPoint(WorldVector<double> &p, ElInfo *oldElInfo, WorldVector<double>* value) const; + template<> void DOFVector<double>::refineInterpol(RCNeighbourList&, int); diff --git a/AMDiS/src/ITL_OEMSolver.hh b/AMDiS/src/ITL_OEMSolver.hh index abd5dc72..a8514b0a 100644 --- a/AMDiS/src/ITL_OEMSolver.hh +++ b/AMDiS/src/ITL_OEMSolver.hh @@ -69,13 +69,16 @@ namespace AMDiS { FUNCNAME("ITL_OEMSolver_para_runner::solve()"); TEST_EXIT(preconPair.l != NULL)("there is no left preconditioner"); TEST_EXIT(preconPair.r != NULL)("there is no right preconditioner"); - itl::cyclic_iteration<typename Vector::value_type> iter(b, oem.getMaxIterations(), oem.getRelative(), + + mtl::dense_vector<typename Matrix::value_type> r(A * x - b); + itl::cyclic_iteration<typename Vector::value_type> iter(r, oem.getMaxIterations(), oem.getRelative(), oem.getTolerance(), oem.getPrint_cycle()); int error = solver(A, x, b, *(preconPair.l), *(preconPair.r), iter, ell); oem.setIterations(iter.iterations()); oem.setResidual(iter.resid()); oem.setErrorCode(error); + return error; } private: @@ -101,13 +104,16 @@ namespace AMDiS { FUNCNAME("ITL_OEMSolver_runner::solve()"); TEST_EXIT(preconPair.l != NULL)("there is no left preconditioner"); TEST_EXIT(preconPair.r != NULL)("there is no right preconditioner"); - itl::cyclic_iteration<typename Matrix::value_type> iter(b, oem.getMaxIterations(), oem.getRelative(), + + mtl::dense_vector<typename Matrix::value_type> r(A * x - b); + itl::cyclic_iteration<typename Matrix::value_type> iter(r, oem.getMaxIterations(), oem.getRelative(), oem.getTolerance(), oem.getPrint_cycle()); int error = solver(A, x, b, *(preconPair.l), *(preconPair.r), iter); oem.setErrorCode(error); oem.setIterations(iter.iterations()); oem.setResidual(iter.resid()); + return error; } private: diff --git a/AMDiS/src/MTL4Solver.h b/AMDiS/src/MTL4Solver.h index 525306d4..c48b9808 100644 --- a/AMDiS/src/MTL4Solver.h +++ b/AMDiS/src/MTL4Solver.h @@ -55,6 +55,11 @@ namespace AMDiS { error = worker.solve(matrix ,mtl_x, mtl_b); + mtl::dense_vector<typename MTLMatrix::value_type> r(mtl_b); + r -= matrix * mtl_x; + double residual = two_norm(r); + MSG("MTL4Solver: ||b-Ax||= %e\n", residual); + mtl_x >> xVecMap; return error; } diff --git a/AMDiS/src/ProblemStat.cc b/AMDiS/src/ProblemStat.cc index 3183c724..f437f85c 100644 --- a/AMDiS/src/ProblemStat.cc +++ b/AMDiS/src/ProblemStat.cc @@ -777,9 +777,12 @@ namespace AMDiS { } if (asmMatrix) { + solver->setMultipleRhs(false); solverMatrix.setMatrix(*systemMatrix); INFO(info, 8)("fillin of assembled matrix: %d\n", nnz); + } else { + solver->setMultipleRhs(true); } #ifdef HAVE_PARALLEL_DOMAIN_AMDIS @@ -973,6 +976,7 @@ namespace AMDiS { TIME_USED(first, clock())); } + bool ProblemStatSeq::dualMeshTraverseRequired() { FUNCNAME("ProblemStat::dualMeshTraverseRequired()"); @@ -1492,6 +1496,7 @@ namespace AMDiS { rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(robin); } + void ProblemStatSeq::addPeriodicBC(BoundaryType type, int row, int col) { FUNCNAME("ProblemStat::addPeriodicBC()"); @@ -1514,6 +1519,8 @@ namespace AMDiS { { FUNCNAME("ProblemStat::addBoundaryOperator()"); + boundaryConditionSet = true; + RobinBC *robin = new RobinBC(type, NULL, op, componentSpaces[row], componentSpaces[col]); @@ -1527,6 +1534,8 @@ namespace AMDiS { { FUNCNAME("ProblemStat::addBoundaryOperator()"); + boundaryConditionSet = true; + RobinBC *robin = new RobinBC(type, op, NULL, componentSpaces[row]); -- GitLab