Commit dfd9bc02 authored by Siqi Ling's avatar Siqi Ling

merge parallel multimesh branch to the trunk

parent 4584272c
...@@ -163,6 +163,10 @@ namespace AMDiS { ...@@ -163,6 +163,10 @@ namespace AMDiS {
template<typename T> class WorldVector; template<typename T> class WorldVector;
template<typename T> class WorldMatrix; template<typename T> class WorldMatrix;
template<typename T> class VectorOfFixVecs; template<typename T> class VectorOfFixVecs;
namespace detail {
template <class P> class CouplingProblemStat;
}
typedef mtl::dense2D<double> ElementMatrix; typedef mtl::dense2D<double> ElementMatrix;
......
...@@ -53,7 +53,6 @@ namespace AMDiS { ...@@ -53,7 +53,6 @@ namespace AMDiS {
Assembler::~Assembler() Assembler::~Assembler()
{} {}
void Assembler::calculateElementMatrix(const ElInfo *elInfo, void Assembler::calculateElementMatrix(const ElInfo *elInfo,
ElementMatrix& userMat, ElementMatrix& userMat,
double factor) double factor)
...@@ -64,19 +63,22 @@ namespace AMDiS { ...@@ -64,19 +63,22 @@ namespace AMDiS {
Element *el = elInfo->getElement(); Element *el = elInfo->getElement();
if (el != lastMatEl || !operat->isOptimized()) { if (el != lastMatEl || !operat->isOptimized()) {
initElement(elInfo, elInfo); initElement(elInfo);
if (rememberElMat) if (rememberElMat)
set_to_zero(elementMatrix); set_to_zero(elementMatrix);
lastMatEl = el; lastMatEl = el;
} else { } else {
// Only possible in single mesh case when one operator
// is used more than twice?
if (rememberElMat) { if (rememberElMat) {
userMat += factor * elementMatrix; if (&userMat != &elementMatrix)
userMat += factor * elementMatrix;
return; return;
} }
} }
ElementMatrix& mat = rememberElMat ? elementMatrix : userMat; ElementMatrix& mat = rememberElMat ? elementMatrix : userMat;
if (secondOrderAssembler) if (secondOrderAssembler)
...@@ -91,8 +93,7 @@ namespace AMDiS { ...@@ -91,8 +93,7 @@ namespace AMDiS {
if (rememberElMat && &userMat != &elementMatrix) if (rememberElMat && &userMat != &elementMatrix)
userMat += factor * elementMatrix; userMat += factor * elementMatrix;
} }
void Assembler::calculateElementMatrix(const ElInfo *rowElInfo, void Assembler::calculateElementMatrix(const ElInfo *rowElInfo,
const ElInfo *colElInfo, const ElInfo *colElInfo,
const ElInfo *smallElInfo, const ElInfo *smallElInfo,
...@@ -101,115 +102,68 @@ namespace AMDiS { ...@@ -101,115 +102,68 @@ namespace AMDiS {
ElementMatrix& userMat, ElementMatrix& userMat,
double factor) double factor)
{ {
if (remember && (factor != 1.0 || operat->uhOld)) Element *el = smallElInfo->getElement();
rememberElMat = true; // initElement and calculateElementMatrix always need to be
// recalculated since the smaller ElInfo can be different
Element *el = smallElInfo->getElement();
lastVecEl = lastMatEl = NULL; lastVecEl = lastMatEl = NULL;
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
initElement(smallElInfo, largeElInfo); initElement(smallElInfo, largeElInfo);
if (el != lastMatEl || !operat->isOptimized()) {
if (rememberElMat)
set_to_zero(elementMatrix);
if (el != lastMatEl || !operat->isOptimized())
lastMatEl = el; lastMatEl = el;
} else { else {
if (rememberElMat) { ERROR_EXIT("Never reached because lastVecEl = lastMatEl = NULL;\n");
if (&userMat != &elementMatrix)
userMat += factor * elementMatrix; userMat += factor * elementMatrix;
return; return;
}
} }
ElementMatrix& mat = rememberElMat ? elementMatrix : userMat;
if (secondOrderAssembler) {
// calculate element matrices always on smallest element
secondOrderAssembler->calculateElementMatrix(smallElInfo, mat);
// smallElInfo stores refinement-relation to largeElInfo // In multimesh case, elementMatrix is always be recalculated, because each time we
ElementMatrix &m = // need to do transformation here.
smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); // muste be moved to next if-else block when generalized for multiple polynomial degrees set_to_zero(elementMatrix);
if (!rowColFeSpaceEqual) { ElementMatrix& mat = elementMatrix;
if (smallElInfo == colElInfo)
tmpMat = m * mat;
else
tmpMat = mat * trans(m);
mat = tmpMat;
}
}
if (firstOrderAssemblerGrdPsi) { if (secondOrderAssembler)
secondOrderAssembler->calculateElementMatrix(smallElInfo, mat);
if (firstOrderAssemblerGrdPsi)
firstOrderAssemblerGrdPsi->calculateElementMatrix(smallElInfo, mat); firstOrderAssemblerGrdPsi->calculateElementMatrix(smallElInfo, mat);
if (firstOrderAssemblerGrdPhi)
if (!rowColFeSpaceEqual) {
if (largeElInfo == rowElInfo) {
ElementMatrix &m =
smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
tmpMat = m * mat;
} else {
ElementMatrix &m =
smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
tmpMat = mat * trans(m);
}
mat = tmpMat;
}
}
if (firstOrderAssemblerGrdPhi) {
firstOrderAssemblerGrdPhi->calculateElementMatrix(smallElInfo, mat); firstOrderAssemblerGrdPhi->calculateElementMatrix(smallElInfo, mat);
if (zeroOrderAssembler)
if (!rowColFeSpaceEqual) {
if (largeElInfo == colElInfo) {
ElementMatrix &m =
smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
tmpMat = mat * trans(m);
} else {
ElementMatrix &m =
smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
tmpMat = m * mat;
}
mat = tmpMat;
}
}
if (zeroOrderAssembler) {
zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat); zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat);
if (!rowColFeSpaceEqual) { ElementMatrix &m =
ElementMatrix &m = smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
if (smallElInfo == colElInfo)
tmpMat = m * mat;
else
tmpMat = mat * trans(m);
mat = tmpMat;
}
}
if (rememberElMat && &userMat != &elementMatrix) if (!rowColFeSpaceEqual) {
userMat += factor * elementMatrix; if (smallElInfo == colElInfo)
tmpMat = m * mat;
else
tmpMat = mat * trans(m);
mat = tmpMat;
} else if (smallElInfo == colElInfo) {
tmpMat = m * mat * trans(m);
mat = tmpMat;
}
// This is for the call in matVecAssemble
if (&userMat != &elementMatrix)
userMat += factor * elementMatrix;
} }
void Assembler::calculateElementVector(const ElInfo *elInfo, void Assembler::calculateElementVector(const ElInfo *elInfo,
ElementVector& userVec, ElementVector& userVec,
double factor) double factor)
{ {
if (remember && factor != 1.0) if (remember && factor != 1.0)
rememberElVec = true; rememberElVec = true;
Element *el = elInfo->getElement(); Element *el = elInfo->getElement();
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
...@@ -221,6 +175,8 @@ namespace AMDiS { ...@@ -221,6 +175,8 @@ namespace AMDiS {
lastVecEl = el; lastVecEl = el;
} else { } else {
// Only possible in single mesh case when one operator
// is used more than twice at dof vector?
if (rememberElVec) { if (rememberElVec) {
userVec += factor * elementVector; userVec += factor * elementVector;
return; return;
...@@ -246,7 +202,6 @@ namespace AMDiS { ...@@ -246,7 +202,6 @@ namespace AMDiS {
userVec += factor * elementVector; userVec += factor * elementVector;
} }
void Assembler::calculateElementVector(const ElInfo *mainElInfo, void Assembler::calculateElementVector(const ElInfo *mainElInfo,
const ElInfo *auxElInfo, const ElInfo *auxElInfo,
const ElInfo *smallElInfo, const ElInfo *smallElInfo,
...@@ -256,36 +211,33 @@ namespace AMDiS { ...@@ -256,36 +211,33 @@ namespace AMDiS {
{ {
FUNCNAME("Assembler::calculateElementVector()"); FUNCNAME("Assembler::calculateElementVector()");
if (remember && factor != 1.0)
rememberElVec = true;
Element *el = mainElInfo->getElement(); Element *el = mainElInfo->getElement();
// initElement and calculateElementVector always need to be
// recalculated since the smaller ElInfo can be different
lastVecEl = lastMatEl = NULL;
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized()) if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
initElement(smallElInfo, largeElInfo); initElement(smallElInfo, largeElInfo);
if (el != lastVecEl || !operat->isOptimized()) { if (el != lastVecEl || !operat->isOptimized())
if (rememberElVec)
set_to_zero(elementVector);
lastVecEl = el; lastVecEl = el;
} else { else {
if (rememberElVec) { ERROR_EXIT("Never reached because lastVecEl = lastMatEl = NULL;\n");
userVec += factor * elementVector; userVec += factor * elementVector;
return; return;
}
} }
ElementVector& vec = rememberElVec ? elementVector : userVec;
set_to_zero(elementVector);
ElementVector& vec = elementVector;
if (operat->uhOld && remember) { if (operat->uhOld && remember) {
if (smallElInfo->getLevel() == largeElInfo->getLevel()) if (smallElInfo->getLevel() == largeElInfo->getLevel())
matVecAssemble(auxElInfo, vec); matVecAssemble(auxElInfo, vec);
else else
matVecAssemble(mainElInfo, auxElInfo, smallElInfo, largeElInfo, vec); matVecAssemble(mainElInfo, auxElInfo, smallElInfo, largeElInfo, vec);
if (rememberElVec) userVec += factor * elementVector;
userVec += factor * elementVector;
return; return;
} }
...@@ -306,13 +258,12 @@ namespace AMDiS { ...@@ -306,13 +258,12 @@ namespace AMDiS {
} }
} }
if (rememberElVec) userVec += factor * elementVector;
userVec += factor * elementVector;
} }
void Assembler::matVecAssemble(const ElInfo *elInfo, ElementVector& vec) void Assembler::matVecAssemble(const ElInfo *elInfo, ElementVector& vec)
{ {
Element *el = elInfo->getElement(); Element *el = elInfo->getElement();
ElementVector uhOldLoc(operat->uhOld->getFeSpace() == rowFeSpace ? ElementVector uhOldLoc(operat->uhOld->getFeSpace() == rowFeSpace ?
nRow : nCol); nRow : nCol);
...@@ -323,7 +274,8 @@ namespace AMDiS { ...@@ -323,7 +274,8 @@ namespace AMDiS {
calculateElementMatrix(elInfo, elementMatrix); calculateElementMatrix(elInfo, elementMatrix);
} }
vec += elementMatrix*uhOldLoc;
vec += elementMatrix * uhOldLoc;
} }
...@@ -331,7 +283,7 @@ namespace AMDiS { ...@@ -331,7 +283,7 @@ namespace AMDiS {
const ElInfo *smallElInfo, const ElInfo *largeElInfo, const ElInfo *smallElInfo, const ElInfo *largeElInfo,
ElementVector& vec) ElementVector& vec)
{ {
FUNCNAME("Assembler::matVecAssemble()"); FUNCNAME("Assembler::matVecAssemble()");
TEST_EXIT(rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts()) TEST_EXIT(rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts())
("Works only for equal basis functions for different components!\n"); ("Works only for equal basis functions for different components!\n");
...@@ -343,7 +295,7 @@ namespace AMDiS { ...@@ -343,7 +295,7 @@ namespace AMDiS {
usedEl = mainElInfo->getElement(); usedEl = mainElInfo->getElement();
else else
ERROR("Mesh is incorrect.\n"); ERROR("Mesh is incorrect.\n");
const BasisFunction *basFcts = rowFeSpace->getBasisFcts(); const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
int nBasFcts = basFcts->getNumber(); int nBasFcts = basFcts->getNumber();
ElementVector uhOldLoc(nBasFcts); ElementVector uhOldLoc(nBasFcts);
...@@ -353,10 +305,11 @@ namespace AMDiS { ...@@ -353,10 +305,11 @@ namespace AMDiS {
if (mainElInfo->getElement() != lastMatEl) { if (mainElInfo->getElement() != lastMatEl) {
set_to_zero(elementMatrix); set_to_zero(elementMatrix);
calculateElementMatrix(mainElInfo, auxElInfo, smallElInfo, largeElInfo, calculateElementMatrix(mainElInfo, auxElInfo, smallElInfo, largeElInfo,
rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix); rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix);
} }
vec += elementMatrix * uhOldLoc; vec += elementMatrix * uhOldLoc;
} }
...@@ -472,4 +425,4 @@ namespace AMDiS { ...@@ -472,4 +425,4 @@ namespace AMDiS {
checkQuadratures(); checkQuadratures();
} }
} }
\ No newline at end of file
...@@ -56,6 +56,8 @@ namespace AMDiS { ...@@ -56,6 +56,8 @@ namespace AMDiS {
FUNCNAME("BoundaryObject::computeReverseMode()"); FUNCNAME("BoundaryObject::computeReverseMode()");
bool reverseMode = false; bool reverseMode = false;
TEST_EXIT_DBG(obj0.el && obj1.el)("BoundaryObject without element pointer.\n");
switch (feSpace->getMesh()->getDim()) { switch (feSpace->getMesh()->getDim()) {
case 2: case 2:
......
...@@ -99,7 +99,7 @@ namespace AMDiS { ...@@ -99,7 +99,7 @@ namespace AMDiS {
#if HAVE_PARALLEL_DOMAIN_AMDIS #if HAVE_PARALLEL_DOMAIN_AMDIS
vector<FixRefinementPatch::EdgeInEl> refineEdges; vector<FixRefinementPatch::EdgeInEl> refineEdges;
FixRefinementPatch::getOtherEl(stack, refineEdges); FixRefinementPatch::getOtherEl(mesh, stack, refineEdges);
// === If the refinement edge must be fixed, add also the other part of this === // === If the refinement edge must be fixed, add also the other part of this ===
// === edge to the refinement patch. === // === edge to the refinement patch. ===
...@@ -110,6 +110,7 @@ namespace AMDiS { ...@@ -110,6 +110,7 @@ namespace AMDiS {
return; return;
Element *otherEl = refineEdges[0].first; Element *otherEl = refineEdges[0].first;
TEST_EXIT_DBG(otherEl->getMesh() == mesh)("Something is wrong.\n");
TraverseStack stack2; TraverseStack stack2;
ElInfo *elInfo2 = ElInfo *elInfo2 =
......
...@@ -40,7 +40,7 @@ namespace AMDiS { ...@@ -40,7 +40,7 @@ namespace AMDiS {
* problem-list, that is filled by addProblem. Alternatively one can a access * problem-list, that is filled by addProblem. Alternatively one can a access
* each problem by an unique name. * each problem by an unique name.
*/ */
class CouplingIterationInterface : public ProblemIterationInterface class CouplingIterationInterface : public virtual ProblemIterationInterface
{ {
public: public:
virtual ~CouplingIterationInterface() {} virtual ~CouplingIterationInterface() {}
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "AMDiS_fwd.h" #include "AMDiS_fwd.h"
#include "ProblemStat.h" #include "ProblemStat.h"
#include "Initfile.h" #include "Initfile.h"
#include <boost/lexical_cast.hpp> #include "utility/to_string.hpp"
namespace AMDiS { namespace AMDiS {
...@@ -43,21 +43,26 @@ namespace AMDiS { ...@@ -43,21 +43,26 @@ namespace AMDiS {
* computations. * computations.
*/ */
template<typename ProblemStatType> template<typename ProblemStatType>
class CouplingProblemStat class CouplingProblemStat : public ProblemStatSeq
{ {
protected:
typedef ProblemStatSeq super;
using super::nComponents;
using super::meshes;
using super::nMeshes;
using super::feSpaces;
using super::name;
using super::refinementManager;
using super::coarseningManager;
public: public:
/// Constructor /// Constructor
CouplingProblemStat(std::string name_) CouplingProblemStat(std::string name_)
: name(name_), : super(name_),
nComponents(0), dim(-1)
nMeshes(0),
refinementManager(NULL),
coarseningManager(NULL)
{} {}
/// Destructor
virtual ~CouplingProblemStat() {}
/// add problem by number /// add problem by number
virtual void addProblem(ProblemStatType* prob) virtual void addProblem(ProblemStatType* prob)
{ {
...@@ -71,112 +76,193 @@ namespace AMDiS { ...@@ -71,112 +76,193 @@ namespace AMDiS {
Flag adoptFlag = INIT_NOTHING) Flag adoptFlag = INIT_NOTHING)
{ FUNCNAME("CouplingProblemStat::initialize()"); { FUNCNAME("CouplingProblemStat::initialize()");
// create one refinement-/coarseningmanager for all problems super::initialize(initFlag - INIT_MESH);
if (refinementManager != NULL && coarseningManager != NULL) {
WARNING("refinement-/coarseningmanager already created\n"); const Flag DEFAULT_INIT = (INIT_FE_SPACE | INIT_MESH | CREATE_MESH | INIT_SYSTEM | INIT_SOLVER | INIT_ESTIMATOR | INIT_MARKER | INIT_FILEWRITER);
} else { for (size_t p = 0; p < problems.size(); ++p) {
if (!adoptProblem) problems[p]->initialize(initFlag - DEFAULT_INIT);
createRefCoarseManager();
else {
refinementManager = adoptProblem->getRefinementManager();
coarseningManager = adoptProblem->getCoarseningManager();
}
} }
if (refinementManager == NULL || coarseningManager == NULL)
WARNING("no refinement-/coarseningmanager created\n");
// create Meshes and FeSpaces for (size_t i = 0; i < meshes.size(); i++) {
int globalRefinements = 0;
// If AMDiS is compiled for parallel computations, the global refinements are
// ignored here. Later, each rank will add the global refinements to its
// private mesh.
#ifndef HAVE_PARALLEL_DOMAIN_AMDIS
Parameters::get(meshes[i]->getName() + "->global refinements",
globalRefinements);
#endif
bool initMesh = initFlag.isSet(INIT_MESH);
// Initialize the meshes if there is no serialization file.
if (initMesh && meshes[i] && !(meshes[i]->isInitialized())) {
meshes[i]->initialize();
refinementManager->globalRefine(meshes[i], globalRefinements);
}
}
}
/// Used in \ref initialize().
virtual void createMesh() override
{
// all problems must have the same dimension (?) // all problems must have the same dimension (?)
int dim = 0; dim = 0;
Parameters::get(name + "->dim", dim); Parameters::get(name + "->dim", dim);
TEST_EXIT(dim)("No problem dimension specified for \"%s->dim\"!\n", TEST_EXIT(dim)("No problem dimension specified for \"%s->dim\"!\n",
name.c_str()); name.c_str());