Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

Commit dfd9bc02 authored by Siqi Ling's avatar Siqi Ling
Browse files

merge parallel multimesh branch to the trunk

parent 4584272c
......@@ -163,6 +163,10 @@ namespace AMDiS {
template<typename T> class WorldVector;
template<typename T> class WorldMatrix;
template<typename T> class VectorOfFixVecs;
namespace detail {
template <class P> class CouplingProblemStat;
}
typedef mtl::dense2D<double> ElementMatrix;
......
......@@ -53,7 +53,6 @@ namespace AMDiS {
Assembler::~Assembler()
{}
void Assembler::calculateElementMatrix(const ElInfo *elInfo,
ElementMatrix& userMat,
double factor)
......@@ -64,19 +63,22 @@ namespace AMDiS {
Element *el = elInfo->getElement();
if (el != lastMatEl || !operat->isOptimized()) {
initElement(elInfo, elInfo);
initElement(elInfo);
if (rememberElMat)
set_to_zero(elementMatrix);
lastMatEl = el;
} else {
// Only possible in single mesh case when one operator
// is used more than twice?
if (rememberElMat) {
userMat += factor * elementMatrix;
if (&userMat != &elementMatrix)
userMat += factor * elementMatrix;
return;
}
}
ElementMatrix& mat = rememberElMat ? elementMatrix : userMat;
if (secondOrderAssembler)
......@@ -91,8 +93,7 @@ namespace AMDiS {
if (rememberElMat && &userMat != &elementMatrix)
userMat += factor * elementMatrix;
}
void Assembler::calculateElementMatrix(const ElInfo *rowElInfo,
const ElInfo *colElInfo,
const ElInfo *smallElInfo,
......@@ -101,115 +102,68 @@ namespace AMDiS {
ElementMatrix& userMat,
double factor)
{
if (remember && (factor != 1.0 || operat->uhOld))
rememberElMat = true;
Element *el = smallElInfo->getElement();
Element *el = smallElInfo->getElement();
// initElement and calculateElementMatrix always need to be
// recalculated since the smaller ElInfo can be different
lastVecEl = lastMatEl = NULL;
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
initElement(smallElInfo, largeElInfo);
if (el != lastMatEl || !operat->isOptimized()) {
if (rememberElMat)
set_to_zero(elementMatrix);
if (el != lastMatEl || !operat->isOptimized())
lastMatEl = el;
} else {
if (rememberElMat) {
else {
ERROR_EXIT("Never reached because lastVecEl = lastMatEl = NULL;\n");
if (&userMat != &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
ElementMatrix &m =
smallElInfo->getSubElemGradCoordsMat(rowFeSpace->getBasisFcts()->getDegree()); // muste be moved to next if-else block when generalized for multiple polynomial degrees
if (!rowColFeSpaceEqual) {
if (smallElInfo == colElInfo)
tmpMat = m * mat;
else
tmpMat = mat * trans(m);
mat = tmpMat;
}
}
// In multimesh case, elementMatrix is always be recalculated, because each time we
// need to do transformation here.
set_to_zero(elementMatrix);
ElementMatrix& mat = elementMatrix;
if (firstOrderAssemblerGrdPsi) {
if (secondOrderAssembler)
secondOrderAssembler->calculateElementMatrix(smallElInfo, mat);
if (firstOrderAssemblerGrdPsi)
firstOrderAssemblerGrdPsi->calculateElementMatrix(smallElInfo, mat);
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) {
if (firstOrderAssemblerGrdPhi)
firstOrderAssemblerGrdPhi->calculateElementMatrix(smallElInfo, mat);
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) {
if (zeroOrderAssembler)
zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat);
if (!rowColFeSpaceEqual) {
ElementMatrix &m =
smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
if (smallElInfo == colElInfo)
tmpMat = m * mat;
else
tmpMat = mat * trans(m);
mat = tmpMat;
}
}
ElementMatrix &m =
smallElInfo->getSubElemCoordsMat(rowFeSpace->getBasisFcts()->getDegree());
if (rememberElMat && &userMat != &elementMatrix)
userMat += factor * elementMatrix;
if (!rowColFeSpaceEqual) {
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,
ElementVector& userVec,
double factor)
{
if (remember && factor != 1.0)
rememberElVec = true;
Element *el = elInfo->getElement();
if ((el != lastMatEl && el != lastVecEl) || !operat->isOptimized())
......@@ -221,6 +175,8 @@ namespace AMDiS {
lastVecEl = el;
} else {
// Only possible in single mesh case when one operator
// is used more than twice at dof vector?
if (rememberElVec) {
userVec += factor * elementVector;
return;
......@@ -246,7 +202,6 @@ namespace AMDiS {
userVec += factor * elementVector;
}
void Assembler::calculateElementVector(const ElInfo *mainElInfo,
const ElInfo *auxElInfo,
const ElInfo *smallElInfo,
......@@ -256,36 +211,33 @@ namespace AMDiS {
{
FUNCNAME("Assembler::calculateElementVector()");
if (remember && factor != 1.0)
rememberElVec = true;
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())
initElement(smallElInfo, largeElInfo);
if (el != lastVecEl || !operat->isOptimized()) {
if (rememberElVec)
set_to_zero(elementVector);
if (el != lastVecEl || !operat->isOptimized())
lastVecEl = el;
} else {
if (rememberElVec) {
userVec += factor * elementVector;
return;
}
else {
ERROR_EXIT("Never reached because lastVecEl = lastMatEl = NULL;\n");
userVec += factor * elementVector;
return;
}
ElementVector& vec = rememberElVec ? elementVector : userVec;
set_to_zero(elementVector);
ElementVector& vec = elementVector;
if (operat->uhOld && remember) {
if (smallElInfo->getLevel() == largeElInfo->getLevel())
matVecAssemble(auxElInfo, vec);
else
else
matVecAssemble(mainElInfo, auxElInfo, smallElInfo, largeElInfo, vec);
if (rememberElVec)
userVec += factor * elementVector;
userVec += factor * elementVector;
return;
}
......@@ -306,13 +258,12 @@ namespace AMDiS {
}
}
if (rememberElVec)
userVec += factor * elementVector;
userVec += factor * elementVector;
}
void Assembler::matVecAssemble(const ElInfo *elInfo, ElementVector& vec)
{
Element *el = elInfo->getElement();
ElementVector uhOldLoc(operat->uhOld->getFeSpace() == rowFeSpace ?
nRow : nCol);
......@@ -323,7 +274,8 @@ namespace AMDiS {
calculateElementMatrix(elInfo, elementMatrix);
}
vec += elementMatrix*uhOldLoc;
vec += elementMatrix * uhOldLoc;
}
......@@ -331,7 +283,7 @@ namespace AMDiS {
const ElInfo *smallElInfo, const ElInfo *largeElInfo,
ElementVector& vec)
{
FUNCNAME("Assembler::matVecAssemble()");
FUNCNAME("Assembler::matVecAssemble()");
TEST_EXIT(rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts())
("Works only for equal basis functions for different components!\n");
......@@ -343,7 +295,7 @@ namespace AMDiS {
usedEl = mainElInfo->getElement();
else
ERROR("Mesh is incorrect.\n");
const BasisFunction *basFcts = rowFeSpace->getBasisFcts();
int nBasFcts = basFcts->getNumber();
ElementVector uhOldLoc(nBasFcts);
......@@ -353,10 +305,11 @@ namespace AMDiS {
if (mainElInfo->getElement() != lastMatEl) {
set_to_zero(elementMatrix);
calculateElementMatrix(mainElInfo, auxElInfo, smallElInfo, largeElInfo,
rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix);
rowFeSpace == operat->uhOld->getFeSpace(), elementMatrix);
}
vec += elementMatrix * uhOldLoc;
}
......@@ -472,4 +425,4 @@ namespace AMDiS {
checkQuadratures();
}
}
}
\ No newline at end of file
......@@ -56,6 +56,8 @@ namespace AMDiS {
FUNCNAME("BoundaryObject::computeReverseMode()");
bool reverseMode = false;
TEST_EXIT_DBG(obj0.el && obj1.el)("BoundaryObject without element pointer.\n");
switch (feSpace->getMesh()->getDim()) {
case 2:
......
......@@ -99,7 +99,7 @@ namespace AMDiS {
#if HAVE_PARALLEL_DOMAIN_AMDIS
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 ===
// === edge to the refinement patch. ===
......@@ -110,6 +110,7 @@ namespace AMDiS {
return;
Element *otherEl = refineEdges[0].first;
TEST_EXIT_DBG(otherEl->getMesh() == mesh)("Something is wrong.\n");
TraverseStack stack2;
ElInfo *elInfo2 =
......
......@@ -40,7 +40,7 @@ namespace AMDiS {
* problem-list, that is filled by addProblem. Alternatively one can a access
* each problem by an unique name.
*/
class CouplingIterationInterface : public ProblemIterationInterface
class CouplingIterationInterface : public virtual ProblemIterationInterface
{
public:
virtual ~CouplingIterationInterface() {}
......
......@@ -31,7 +31,7 @@
#include "AMDiS_fwd.h"
#include "ProblemStat.h"
#include "Initfile.h"
#include <boost/lexical_cast.hpp>
#include "utility/to_string.hpp"
namespace AMDiS {
......@@ -43,21 +43,26 @@ namespace AMDiS {
* computations.
*/
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:
/// Constructor
CouplingProblemStat(std::string name_)
: name(name_),
nComponents(0),
nMeshes(0),
refinementManager(NULL),
coarseningManager(NULL)
: super(name_),
dim(-1)
{}
/// Destructor
virtual ~CouplingProblemStat() {}
/// add problem by number
virtual void addProblem(ProblemStatType* prob)
{
......@@ -71,112 +76,193 @@ namespace AMDiS {
Flag adoptFlag = INIT_NOTHING)
{ FUNCNAME("CouplingProblemStat::initialize()");
// create one refinement-/coarseningmanager for all problems
if (refinementManager != NULL && coarseningManager != NULL) {
WARNING("refinement-/coarseningmanager already created\n");
} else {
if (!adoptProblem)
createRefCoarseManager();
else {
refinementManager = adoptProblem->getRefinementManager();
coarseningManager = adoptProblem->getCoarseningManager();
}
super::initialize(initFlag - INIT_MESH);
const Flag DEFAULT_INIT = (INIT_FE_SPACE | INIT_MESH | CREATE_MESH | INIT_SYSTEM | INIT_SOLVER | INIT_ESTIMATOR | INIT_MARKER | INIT_FILEWRITER);
for (size_t p = 0; p < problems.size(); ++p) {
problems[p]->initialize(initFlag - DEFAULT_INIT);
}
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 (?)
int dim = 0;
dim = 0;
Parameters::get(name + "->dim", dim);
TEST_EXIT(dim)("No problem dimension specified for \"%s->dim\"!\n",
name.c_str());
std::map<std::string, Mesh*> meshByName;
std::map<std::pair<std::string, int>, Mesh*> meshByName; // (name, refSet) --> Mesh*
typedef std::map<std::pair<std::string, int>, Mesh*>::iterator MeshIterator;
std::vector<std::set<Mesh*> > meshesForProblems(problems.size());
std::map<std::pair<Mesh*, int>, FiniteElemSpace*> feSpaceMap;
for (size_t i = 0; i < problems.size(); ++i) {
TEST_EXIT(problems[i])("problem[%d] does not exist!\n",i);
for (size_t j = 0; j < problems[i]->getNumComponents(); j++) {
// mesh
int nComponents = problems[i]->getNumComponents();
int nAddComponents = 0;
Parameters::get(problems[i]->getName() + "->additional components", nAddComponents);
problems[i]->componentMeshes.resize(nComponents + nAddComponents);
for (size_t j = 0; j < nComponents + nAddComponents; j++) {
// name of the mesh
std::string meshName("");
Parameters::get(problems[i]->getName() + "->mesh", meshName);
TEST_EXIT(meshName != "")("No mesh name specified for \"%s->mesh\"!\n",
problems[i]->getName().c_str());
if (meshByName.find(meshName) == meshByName.end()) {
// dimension of the mesh
int mesh_dim = 0;
Parameters::get(problems[i]->getName() + "->dim", mesh_dim);
TEST_EXIT(dim == mesh_dim)("Mesh-dimension must be the same for all problems!\n");
// refinement set (optional)
int refSet = 0;
Parameters::get(problems[i]->getName() + "->refinement set[" + to_string(j) + "]", refSet);
// create a new Mesh only if not already created for other problem
Mesh* componentMesh;
MeshIterator meshIt = meshByName.find(std::make_pair(meshName, refSet));
if (meshIt == meshByName.end()) {
Mesh *newMesh = new Mesh(meshName, dim);
meshByName[meshName] = newMesh;
meshes.push_back(newMesh);
meshesForProblems[i].insert(newMesh);
meshByName[std::make_pair(meshName, refSet)] = newMesh;
componentMesh = newMesh;
nMeshes++;
} else
meshesForProblems[i].insert(meshByName[meshName]);
} else {
componentMesh = meshIt->second;
}
problems[i]->componentMeshes[j] = componentMesh;
}
// copy unqiue set of meshes to problem[i]->meshes
std::set<Mesh*> uniqueMeshes;
for (size_t j = 0; j < problems[i]->componentMeshes.size(); ++j)
uniqueMeshes.insert(problems[i]->componentMeshes[j]);
problems[i]->meshes.clear();
problems[i]->meshes.insert(problems[i]->meshes.begin(), uniqueMeshes.begin(), uniqueMeshes.end());
}
}
problems[i]->setComponentMesh(j, meshByName[meshName]);
/// Used in \ref initialize().
virtual void createFeSpace(DOFAdmin *admin) override
{
std::vector<std::set<FiniteElemSpace const*> > feSpacesForProblems(problems.size());
std::map<std::pair<Mesh*, std::string>, FiniteElemSpace*> feSpaceMap;
for (size_t p = 0; p < problems.size(); ++p) {
TEST_EXIT(problems[p])("problem[%d] does not exist!\n",p);
int nComponents = problems[p]->getNumComponents();
int nAddComponents = 0;
Parameters::get(problems[p]->getName() + "->additional components", nAddComponents);
problems[p]->componentSpaces.resize(nComponents + nAddComponents, NULL);
problems[p]->traverseInfo.resize(nComponents);
for (size_t i = 0; i < nComponents + nAddComponents; i++) {
std::string componentString = "[" + to_string(i) + "]";
std::string feSpaceName = "";
std::string initFileStr = problems[p]->getName() + "->feSpace" + componentString;
Parameters::get(initFileStr, feSpaceName);
// synonym for "feSpace"
if (feSpaceName.size() == 0) {
initFileStr = problems[p]->getName() + "->finite element space" + componentString;
Parameters::get(initFileStr, feSpaceName);
}
// for backward compatibility also accept the old syntax
if (feSpaceName.size() == 0) {
int degree = 1;
initFileStr = problems[p]->getName() + "->polynomial degree" + componentString;
Parameters::get(initFileStr, degree);
TEST_EXIT(degree > 0)
("Poynomial degree in component %d must be larger than zero!\n", i);
feSpaceName = "Lagrange" + to_string(degree);
}
if (feSpaceName.size() == 0)
feSpaceName = "Lagrange1";
if (feSpaceMap[std::make_pair(problems[p]->componentMeshes[i], feSpaceName)] == NULL) {