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 {
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() {}
......
This diff is collapsed.
......@@ -36,7 +36,7 @@ namespace AMDiS {
*
* \brief
*/
class CouplingTimeInterface : public ProblemTimeInterface
class CouplingTimeInterface : public virtual ProblemTimeInterface
{
public:
void addTimeInterface(ProblemTimeInterface *interface)
......
......@@ -344,6 +344,16 @@ namespace AMDiS {
{
return nnzPerRow;
}
std::vector<DegreeOfFreedom>& getRowIndices()
{
return rowIndices;
}
std::vector<DegreeOfFreedom>& getColIndices()
{
return colIndices;
}
/// Writes the matrix to an output stream.
void serialize(std::ostream &out);
......
......@@ -71,7 +71,7 @@ namespace AMDiS {
io::VtkWriter::writeFile(tmp, filename + lexical_cast<std::string>(myRank) + ".vtu",
io::VtkWriter::ASCII,
false,
false);
false);
}
}
#endif
......@@ -751,8 +751,7 @@ namespace AMDiS {
elInfo = stack.traverseNext(elInfo);
}
}
void testSortedDofs(Mesh *mesh, ElementIdxToDofs &elMap)
{
FUNCNAME("debug::dbgTestElementMap()");
......@@ -797,6 +796,64 @@ namespace AMDiS {
}
void createNodeCoords(Mesh *mesh, ElementIdxToCoords& coords)
{
TraverseStack stack;
ElInfo *elInfo =
stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS);
while (elInfo) {
coords.insert(std::make_pair(elInfo->getElement()->getIndex(), elInfo->getCoords()));
elInfo = stack.traverseNext(elInfo);
}
}
void testNodeCoords(Mesh* mesh, ElementIdxToCoords& coords)
{
FUNCNAME("debug::testNodeCoords()");
int dim = mesh->getDim();
TraverseStack stack;
ElInfo *elInfo =
stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS);
while (elInfo) {
Element *el = elInfo->getElement();
FixVec<WorldVector<double>, VERTEX> elCoords = elInfo->getCoords();
for (size_t i = 0; i < (size_t)(size(elCoords)); i++)
for (size_t j = 0; j < (size_t)(mesh->getDim()); j++)
if(elCoords[i][j] != coords[el->getIndex()][i][j]) {
MSG("[DBG] Wrong coordnate on element = %d, vertex index = %d\n!", el->getIndex(), i);
switch (dim) {
case 2:
std::cout << "[DBG]: one coord is: ";
std::cout << "(" << elCoords[i][0] << ", " << elCoords[i][1]<< ") ";
std::cout << "another is: ";
std::cout << "(" << coords[el->getIndex()][i][0] << ", " << coords[el->getIndex()][i][1] << ")\n";
break;
case 3:
std::cout << "[DBG]: one coord is: ";
std::cout << "(" << elCoords[i][0] << ", " << elCoords[i][1]<< ", " << elCoords[i][2] << ") ";
std::cout << "another is: ";
std::cout << "(" << coords[el->getIndex()][i][0] << ", " << coords[el->getIndex()][i][1]
<< ". " << coords[el->getIndex()][i][2] << ")\n";
break;
default:
ERROR_EXIT("What is this?\n");
}
ERROR_EXIT("Mesh vertex coords don't match!\n");
}
elInfo = stack.traverseNext(elInfo);
}
}
void sortDofs(const DegreeOfFreedom* dof0,
const DegreeOfFreedom* dof1,
const DegreeOfFreedom* dof2,
......
......@@ -28,6 +28,7 @@
#include <set>
#include "AMDiS_fwd.h"
#include "Global.h"
#include "FixVec.h"
namespace AMDiS {
......@@ -41,6 +42,7 @@ namespace AMDiS {
};
typedef std::map<int, DofContainer> ElementIdxToDofs;
typedef std::map<int, FixVec<WorldVector<double>, VERTEX> > ElementIdxToCoords;
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
void writeLocalElementDofs(int rank,
......@@ -185,6 +187,10 @@ namespace AMDiS {
void exportDofVectorByCoords(const DOFVector<double>* vec,
std::string filename);
void createNodeCoords(Mesh *mesh, ElementIdxToCoords& coords);
void testNodeCoords(Mesh* mesh, ElementIdxToCoords& coords);
/** \brief
* Traverse a mesh and store for each element all its vertex DOFs in local sorted
* order (by values).
......
......@@ -875,4 +875,4 @@ namespace AMDiS {
{
return getSubElemCoordsMat(degree);
}
}
}
\ No newline at end of file
......@@ -67,6 +67,11 @@ namespace AMDiS {
elementData->deleteDecorated();
delete elementData;
}
// if (dof) {
// delete [] dof;
// dof = NULL;
// }
}
......@@ -146,7 +151,8 @@ namespace AMDiS {
if (dof[j]) {
if (deletedDOFs.count(dof[j]) == 0) {
deletedDOFs[dof[j]] = true;
delete [] dof[j];
// delete [] dof[j];
mesh->freeDof(dof[j], position);
}
}
j++;
......
......@@ -1963,7 +1963,6 @@ namespace AMDiS {
RCNeighbourList* list,
int n, BasisFunction* basFct)
{
FUNCNAME_DBG("Lagrange::refineInter4_3d");
if (n < 1)
return;
......
......@@ -89,6 +89,7 @@ namespace AMDiS {
vector<DegreeOfFreedom> Mesh::dof_used;
const int Mesh::MAX_DOF = 100;
map<pair<DegreeOfFreedom, int>, DegreeOfFreedom*> Mesh::serializedDOFs;
std::set<string> Mesh::refinedMeshNames;
Mesh::Mesh(string aName, int dimension)
: name(aName),
......@@ -236,7 +237,7 @@ namespace AMDiS {
// for the vector index the corresponding element is stored in.
// 3. Get this element from macroElements, and set it as the i-th
// neighbour for the current element.
if((*it)->getNeighbour(i)!=NULL) {
if ((*it)->getNeighbour(i)!=NULL) {
macroElements[insertCounter]->
setNeighbour(i, macroElements[mapIndex[(*it)->getNeighbour(i)->getIndex()]]);
}
......@@ -275,6 +276,50 @@ namespace AMDiS {
me->setIndex(macroElements.size());
}
void Mesh::removeAllMacroElements()
{
// Delete all the dofs
Element::deletedDOFs.clear();
for (deque<MacroElement*>::const_iterator it = macroElements.begin();
it != macroElements.end(); ++it) {
(*it)->getElement()->deleteElementDOFs();
}
Element::deletedDOFs.clear();
// Set all neighbors null
for (deque<MacroElement*>::const_iterator macroIt = macroElements.begin();
macroIt != macroElements.end(); ++macroIt) {
for (int i = 0; i < getGeo(NEIGH); i++)
(*macroIt)->setNeighbour(i, NULL);
Element *mel = (*macroIt)->getElement();
// Delete element hierarchie
if (!(mel->isLeaf())) {
delete mel->getChild(0);
delete mel->getChild(1);
mel->child[0] = NULL;
mel->child[1] = NULL;
mel->setElementData(elementDataPrototype->clone());
}
}
macroElements.clear();
nLeaves = 0;
nElements = 0;
nVertices = 0;
for (size_t i = 0; i < admin.size(); i++)
{
TEST_EXIT_DBG(admin[i]->getUsedSize() == admin[i]->getHoleCount())
("All macro elements has been removed. But not all dofs are cleaned. (UsedSize = %d, HoleCount = %d)\n",
admin[i]->getUsedSize(), admin[i]->getHoleCount());
admin[i]->reset();
}
}
void Mesh::removeMacroElements(std::set<MacroElement*>& delMacros,
vector<const FiniteElemSpace*>& feSpaces)
......@@ -577,6 +622,7 @@ namespace AMDiS {
return;