Commit f96caf23 authored by Thomas Witkowski's avatar Thomas Witkowski

Fixed a very special refinement bug occured only in parallel computations.

parent 067ba67d
......@@ -49,10 +49,10 @@ namespace AMDiS {
{
public:
/// Type of scalars in the underlying matrix
typedef double value_type;
typedef double value_type;
/// Type of underlying matrix
typedef mtl::compressed2D<value_type> base_matrix_type;
typedef mtl::compressed2D<value_type> base_matrix_type;
/// Type of inserter for the base matrix;
typedef mtl::matrix::inserter<base_matrix_type, mtl::operations::update_plus<value_type> > inserter_type;
......
......@@ -62,11 +62,11 @@ namespace AMDiS {
}
void writeElementIndexMesh(FiniteElemSpace *feSpace, std::string filename)
void writeElementIndexMesh(Mesh *mesh, std::string filename)
{
std::map<int, double> vec;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(feSpace->getMesh(), -1, Mesh::CALL_LEAF_EL);
ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
while (elInfo) {
int index = elInfo->getElement()->getIndex();
......@@ -74,16 +74,15 @@ namespace AMDiS {
elInfo = stack.traverseNext(elInfo);
}
ElementFileWriter::writeFile(vec, feSpace, filename);
ElementFileWriter::writeFile(vec, mesh, filename);
}
void highlightElementIndexMesh(FiniteElemSpace *feSpace, int idx,
std::string filename)
void highlightElementIndexMesh(Mesh *mesh, int idx, std::string filename)
{
std::map<int, double> vec;
TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(feSpace->getMesh(), -1, Mesh::CALL_LEAF_EL);
ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL);
while (elInfo) {
int index = elInfo->getElement()->getIndex();
......@@ -91,7 +90,7 @@ namespace AMDiS {
elInfo = stack.traverseNext(elInfo);
}
ElementFileWriter::writeFile(vec, feSpace, filename);
ElementFileWriter::writeFile(vec, mesh, filename);
}
......
......@@ -72,10 +72,9 @@ namespace AMDiS {
* \param[in] feSpace The FE space to be used.
* \param[in] filename Name of the file.
*/
void writeElementIndexMesh(FiniteElemSpace *feSpace, std::string filename);
void writeElementIndexMesh(Mesh *mesh, std::string filename);
void highlightElementIndexMesh(FiniteElemSpace *feSpace, int idx,
std::string filename);
void highlightElementIndexMesh(Mesh *mesh, int idx, std::string filename);
void colorDofVectorByLocalElementDofs(DOFVector<double>& vec, Element *el);
......
......@@ -7,7 +7,7 @@
namespace AMDiS {
ElementFileWriter::ElementFileWriter(std::string name_,
const FiniteElemSpace *feSpace_,
Mesh *mesh_,
std::map<int, double> &mapvec)
: name(name_),
tecplotExt(".plt"),
......@@ -21,8 +21,7 @@ namespace AMDiS {
indexDecimals(3),
tsModulo(1),
timestepNumber(-1),
mesh(feSpace_->getMesh()),
feSpace(feSpace_),
mesh(mesh_),
vec(mapvec)
{
if (name != "") {
......@@ -93,10 +92,10 @@ namespace AMDiS {
void ElementFileWriter::writeFile(std::map<int, double> &vec,
const FiniteElemSpace *feSpace,
Mesh *mesh,
std::string filename)
{
ElementFileWriter efw("", feSpace, vec);
ElementFileWriter efw("", mesh, vec);
efw.writeVtkValues(filename);
}
......
......@@ -22,7 +22,7 @@ namespace AMDiS {
public:
/// Constructor.
ElementFileWriter(std::string name,
const FiniteElemSpace *feSpace,
Mesh *mesh,
std::map<int, double> &vec);
/// Implementation of FileWriterInterface::writeFiles().
......@@ -33,7 +33,7 @@ namespace AMDiS {
/// Simple writing procedure for one element map.
static void writeFile(std::map<int, double> &vec,
const FiniteElemSpace *feSpace,
Mesh *mesh,
std::string filename);
protected:
......@@ -101,9 +101,6 @@ namespace AMDiS {
/// Mesh used for output.
Mesh *mesh;
/// fespace used for output.
const FiniteElemSpace *feSpace;
/// Vector that stores the solution.
std::map<int, double> vec;
};
......
......@@ -620,6 +620,7 @@ namespace AMDiS {
createPrecon();
}
void ProblemScal::writeResidualMesh(AdaptInfo *adaptInfo, std::string name)
{
FUNCNAME("ProblemScal::writeResidualMesh()");
......@@ -634,10 +635,11 @@ namespace AMDiS {
elInfo = stack.traverseNext(elInfo);
}
ElementFileWriter fw(name, this->getFeSpace(), vec);
ElementFileWriter fw(name, this->getMesh(), vec);
fw.writeFiles(adaptInfo, true);
}
void ProblemScal::createPrecon()
{
std::string preconType("no");
......@@ -646,15 +648,16 @@ namespace AMDiS {
CreatorInterface<ITL_BasePreconditioner> *preconCreator =
CreatorMap<ITL_BasePreconditioner>::getCreator(preconType);
solver->setLeftPrecon( preconCreator->create(systemMatrix->getBaseMatrix()) );
solver->setLeftPrecon(preconCreator->create(systemMatrix->getBaseMatrix()));
preconType= "no";
GET_PARAMETER(0, name + "->solver->right precon", &preconType);
preconCreator = CreatorMap<ITL_BasePreconditioner>::getCreator(preconType);
solver->setRightPrecon( preconCreator->create(systemMatrix->getBaseMatrix()) );
solver->setRightPrecon(preconCreator->create(systemMatrix->getBaseMatrix()));
}
void ProblemScal::serialize(std::ostream &out)
{
FUNCNAME("ProblemScal::serialize()");
......@@ -663,6 +666,7 @@ namespace AMDiS {
solution->serialize(out);
}
void ProblemScal::deserialize(std::istream &in)
{
FUNCNAME("ProblemScal::deserialize()");
......
......@@ -1538,7 +1538,7 @@ namespace AMDiS {
elInfo = stack.traverseNext(elInfo);
}
ElementFileWriter::writeFile(vec, this->getFeSpace(comp), name);
ElementFileWriter::writeFile(vec, this->getMesh(comp), name);
}
......
......@@ -259,6 +259,7 @@ namespace AMDiS {
}
}
void RCNeighbourList::removeDOFParent(int index)
{
Tetrahedron *el = dynamic_cast<Tetrahedron*>(rclist[index]->el);
......@@ -297,6 +298,7 @@ namespace AMDiS {
}
}
RCNeighbourList *RCNeighbourList::periodicSplit(DegreeOfFreedom *edge[2],
DegreeOfFreedom *nextEdge[2],
int *n_neigh,
......
......@@ -12,10 +12,11 @@
#include "Projection.h"
#include "LeafData.h"
#include "VertexVector.h"
#include "Debug.h"
namespace AMDiS {
ElInfo* RefinementManager2d::refineFunction(ElInfo* el_info)
ElInfo* RefinementManager2d::refineFunction(ElInfo* elInfo)
{
FUNCNAME("RefinementManager::refineFunction()");
......@@ -23,41 +24,38 @@ namespace AMDiS {
DegreeOfFreedom *edge[2];
RCNeighbourList* refineList = new RCNeighbourList(2);
if (el_info->getElement()->getMark() <= 0) {
if (elInfo->getElement()->getMark() <= 0) {
delete refineList;
// Element may not be refined.
return el_info;
return elInfo;
}
refineList->setElement(0, el_info->getElement());
refineList->setElement(0, elInfo->getElement());
int n_neigh = 1;
if (el_info->getProjection(0) &&
el_info->getProjection(0)->getType() == VOLUME_PROJECTION)
if (elInfo->getProjection(0) &&
elInfo->getProjection(0)->getType() == VOLUME_PROJECTION)
newCoords = true;
// === Give the refinement edge the right orientation. ===
if (el_info->getElement()->getDOF(0,0) < el_info->getElement()->getDOF(1, 0)) {
edge[0] = const_cast<int*>(el_info->getElement()->getDOF(0));
edge[1] = const_cast<int*>(el_info->getElement()->getDOF(1));
if (elInfo->getElement()->getDOF(0, 0) < elInfo->getElement()->getDOF(1, 0)) {
edge[0] = const_cast<int*>(elInfo->getElement()->getDOF(0));
edge[1] = const_cast<int*>(elInfo->getElement()->getDOF(1));
} else {
edge[1] = const_cast<int*>(el_info->getElement()->getDOF(0));
edge[0] = const_cast<int*>(el_info->getElement()->getDOF(1));
edge[1] = const_cast<int*>(elInfo->getElement()->getDOF(0));
edge[0] = const_cast<int*>(elInfo->getElement()->getDOF(1));
}
// === Get the refinement patch. ===
if (getRefinePatch(&el_info, edge, 0, refineList, &n_neigh)) {
// Domain's boundary was reached while looping around the refinement edge.
getRefinePatch(&el_info, edge, 1, refineList, &n_neigh);
bound = true;
}
getRefinePatch(&elInfo, edge, 0, refineList, &n_neigh);
// === Check for periodic boundary ===
DegreeOfFreedom *next_edge[2];
DegreeOfFreedom *next_edge[2] = {NULL, NULL};
DegreeOfFreedom *first_edge[2] = {edge[0], edge[1]};
DegreeOfFreedom *last_edge[2] = {NULL, NULL};
int n_neigh_periodic;
......@@ -121,25 +119,25 @@ namespace AMDiS {
delete refineList;
return el_info;
return elInfo;
}
void RefinementManager2d::newCoordsFct(ElInfo *el_info)
void RefinementManager2d::newCoordsFct(ElInfo *elInfo)
{
Element *el = el_info->getElement();
Element *el = elInfo->getElement();
int dow = Global::getGeo(WORLD);
Projection *projector = el_info->getProjection(0);
Projection *projector = elInfo->getProjection(0);
if (!projector || projector->getType() != VOLUME_PROJECTION)
projector = el_info->getProjection(2);
projector = elInfo->getProjection(2);
if (el->getFirstChild() && projector && (!el->isNewCoordSet())) {
WorldVector<double> *new_coord = new WorldVector<double>;
for (int j = 0; j < dow; j++)
(*new_coord)[j] = (el_info->getCoord(0)[j] + el_info->getCoord(1)[j]) * 0.5;
(*new_coord)[j] = (elInfo->getCoord(0)[j] + elInfo->getCoord(1)[j]) * 0.5;
projector->project(*new_coord);
el->setNewCoord(new_coord);
......@@ -235,10 +233,10 @@ namespace AMDiS {
void RefinementManager2d::bisectTriangle(Triangle *el, DegreeOfFreedom* newDOFs[3])
{
FUNCNAME("RefinementManager2d::bisectTriangle()");
TEST_EXIT_DBG(mesh)("no mesh!\n");
Triangle *child[2];
child[0] = dynamic_cast<Triangle*>(mesh->createNewElement(el));
child[1] = dynamic_cast<Triangle*>(mesh->createNewElement(el));
......@@ -302,36 +300,47 @@ namespace AMDiS {
}
int RefinementManager2d::getRefinePatch(ElInfo **el_info,
void RefinementManager2d::getRefinePatch(ElInfo **elInfo,
DegreeOfFreedom *edge[2],
int dir, RCNeighbourList* refineList,
int *n_neigh)
{
FUNCNAME("RefinementManager2d::getRefinePatch()");
if ((*el_info)->getNeighbour(2) && (*el_info)->getOppVertex(2) != 2) {
if ((*elInfo)->getNeighbour(2) && (*elInfo)->getOppVertex(2) != 2) {
// Neighbour is not compatible devisible; refine neighbour first, store the
// opp_vertex to traverse back to el.
int opp_vertex = (*el_info)->getOppVertex(2);
int opp_vertex = (*elInfo)->getOppVertex(2);
ElInfo *neigh_info = stack->traverseNeighbour2d(*el_info, 2);
ElInfo *neigh_info = stack->traverseNeighbour2d(*elInfo, 2);
neigh_info->getElement()->setMark(max(neigh_info->getElement()->getMark(), 1));
neigh_info = refineFunction(neigh_info);
// Now go back to the original element and refine the patch.
*el_info = neigh_info = stack->traverseNeighbour2d(neigh_info, opp_vertex);
// === Now go back to the original element and refine the patch. ===
// In Debug mode we test if traverNeighbour2d returns the expected element.
#if (DEBUG != 0)
int testIndex = neigh_info->getNeighbour(opp_vertex)->getIndex();
#endif
*elInfo = neigh_info = stack->traverseNeighbour2d(neigh_info, opp_vertex);
TEST_EXIT_DBG(testIndex == (*elInfo)->getElement()->getIndex())
("Got wrong neighbour! Should be %d, but is %d!\n",
testIndex, (*elInfo)->getElement()->getIndex());
TEST_EXIT_DBG(neigh_info->getElement() ==
dynamic_cast<Triangle*>(const_cast<Element*>((*el_info)->getElement())))
dynamic_cast<Triangle*>(const_cast<Element*>((*elInfo)->getElement())))
("invalid traverse_neighbour1\n");
}
if (refineList->setElement(1, (*el_info)->getNeighbour(2))) {
TEST_EXIT_DBG((*el_info)->getOppVertex(2) == 2)
if (refineList->setElement(1, (*elInfo)->getNeighbour(2))) {
TEST_EXIT_DBG((*elInfo)->getOppVertex(2) == 2)
("no compatible ref. edge after recursive refinement of neighbour\n");
*n_neigh = 2;
}
return 0;
}
}
......@@ -54,15 +54,16 @@ namespace AMDiS {
* get_refine_patch returns 1 if the domain's boundary is reached while
* looping around the refinement edge, otherwise 0
*/
int getRefinePatch(ElInfo **el_info, DegreeOfFreedom *edge[2], int dir,
RCNeighbourList* refineList, int *n_neigh);
void getRefinePatch(ElInfo **elInfo, DegreeOfFreedom *edge[2], int dir,
RCNeighbourList* refineList, int *n_neigh);
/// Refines all elements in the patch.
DegreeOfFreedom refinePatch(DegreeOfFreedom *edge[2], RCNeighbourList* refineList,
DegreeOfFreedom refinePatch(DegreeOfFreedom *edge[2],
RCNeighbourList* refineList,
int n_neigh, bool bound);
/// Implements RefinementManager::refineFunction.
ElInfo* refineFunction(ElInfo* el_info);
ElInfo* refineFunction(ElInfo* elInfo);
/// Refines one Triangle.
void bisectTriangle(Triangle *el, DegreeOfFreedom* newDofs[3]);
......
......@@ -135,9 +135,8 @@ namespace AMDiS {
currentMacro = traverse_mesh->firstMacroElement();
while (((*currentMacro)->getIndex() % maxThreads != myThreadId) &&
(currentMacro != traverse_mesh->endOfMacroElements())) {
currentMacro++;
}
currentMacro != traverse_mesh->endOfMacroElements())
currentMacro++;
if (currentMacro == traverse_mesh->endOfMacroElements())
return NULL;
......@@ -349,13 +348,8 @@ namespace AMDiS {
int fillIthChild = info_stack[stack_used];
info_stack[stack_used]++;
if (traverse_fill_flag.isSet(Mesh::CALL_REVERSE_MODE)) {
if (fillIthChild == 0)
fillIthChild = 1;
else
fillIthChild = 0;
}
if (traverse_fill_flag.isSet(Mesh::CALL_REVERSE_MODE))
fillIthChild = 1 - fillIthChild;
elinfo_stack[stack_used + 1]->fillElInfo(fillIthChild, elinfo_stack[stack_used]);
stack_used++;
......@@ -450,7 +444,8 @@ namespace AMDiS {
case 3:
return traverseNeighbour3d(elinfo_old, neighbour);
break;
default: ERROR_EXIT("invalid dim\n");
default:
ERROR_EXIT("invalid dim\n");
}
return NULL;
}
......@@ -461,11 +456,12 @@ namespace AMDiS {
FUNCNAME("TraverseStackLLtraverseNeighbour3d()");
Element *el2;
ElInfo *old_elinfo, *elinfo, *elinfo2;
ElInfo *elinfo2;
const DegreeOfFreedom *dof;
int i, nb, opp_vertex, stack2_used, typ = 0;
int sav_index, sav_neighbour = neighbour;
int stack2_used;
int sav_neighbour = neighbour;
// father.neigh[coarse_nb[i][j]] == child[i-1].neigh[j]
static int coarse_nb[3][3][4] = {{{-2,-2,-2,-2}, {-1,2,3,1}, {-1,3,2,0}},
{{-2,-2,-2,-2}, {-1,2,3,1}, {-1,2,3,0}},
{{-2,-2,-2,-2}, {-1,2,3,1}, {-1,2,3,0}}};
......@@ -473,26 +469,29 @@ namespace AMDiS {
TEST_EXIT_DBG(stack_used > 0)("no current element\n");
Parametric *parametric = traverse_mesh->getParametric();
if (parametric)
elinfo_old = parametric->removeParametricInfo(elinfo_old);
TEST_EXIT_DBG(elinfo_old == elinfo_stack[stack_used])
("invalid old elinfo\n");
TEST_EXIT_DBG(elinfo_old == elinfo_stack[stack_used])("invalid old elinfo\n");
TEST_EXIT_DBG(elinfo_stack[stack_used]->getFillFlag().isSet(Mesh::FILL_NEIGH))
("FILL_NEIGH not set");
Element *el = elinfo_stack[stack_used]->getElement();
sav_index = el->getIndex();
int sav_index = el->getIndex();
/* first, goto to leaf level, if necessary... */
if ((traverse_fill_flag & Mesh::CALL_LEAF_EL).isAnySet()) {
if ((el->getChild(0)) && (neighbour < 2)) {
if (el->getChild(0) && neighbour < 2) {
if (stack_used >= stack_size - 1)
enlargeTraverseStack();
i = 1 - neighbour;
int i = 1 - neighbour;
elinfo_stack[stack_used + 1]->fillElInfo(i, elinfo_stack[stack_used]);
info_stack[stack_used] = i + 1;
if (traverse_fill_flag.isSet(Mesh::CALL_REVERSE_MODE))
info_stack[stack_used] = (i == 0 ? 2 : 1);
else
info_stack[stack_used] = i + 1;
stack_used++;
info_stack[stack_used] = 0;
neighbour = 3;
......@@ -502,30 +501,43 @@ namespace AMDiS {
/* save information about current element and its position in the tree */
save_traverse_mel = traverse_mel;
save_stack_used = stack_used;
for (int i = stack_used; i <= save_stack_used; i++) {
save_info_stack[i] = info_stack[i];
*(save_elinfo_stack[i]) = *(elinfo_stack[i]);
}
ElInfo *old_elinfo = save_elinfo_stack[save_stack_used];
int opp_vertex = old_elinfo->getOppVertex(neighbour);
nb = neighbour;
// === First phase (see 2D). ===
int nb = neighbour;
while (stack_used > 1) { /* go up in tree until we can go down again */
stack_used--;
typ = elinfo_stack[stack_used]->getType();
nb = coarse_nb[typ][info_stack[stack_used]][nb];
int typ = elinfo_stack[stack_used]->getType();
int elIsIthChild = info_stack[stack_used];
if (traverse_fill_flag.isSet(Mesh::CALL_REVERSE_MODE) && elIsIthChild != 0)
elIsIthChild = (elIsIthChild == 1 ? 2 : 1);
TEST_EXIT_DBG(!elinfo_stack[stack_used + 1]->getParent() ||
elinfo_stack[stack_used + 1]->getParent()->getChild(elIsIthChild - 1) ==
elinfo_stack[stack_used + 1]->getElement())
("Should not happen!\n");
nb = coarse_nb[typ][elIsIthChild][nb];
if (nb == -1)
break;
TEST_EXIT_DBG(nb >= 0)("invalid coarse_nb %d\n",nb);
}
/* save hierarchy information about current element */
for (i = stack_used; i <= save_stack_used; i++) {
save_info_stack[i] = info_stack[i];
*(save_elinfo_stack[i]) = *(elinfo_stack[i]);
}
old_elinfo = save_elinfo_stack[save_stack_used];
opp_vertex = old_elinfo->getOppVertex(neighbour);
if (nb >= 0) {
// Go to macro element neighbour.
if (nb >= 0) { /* go to macro element neighbour */
i = traverse_mel->getOppVertex(nb);
int i = traverse_mel->getOppVertex(nb);
traverse_mel = traverse_mel->getNeighbour(nb);
if (traverse_mel == NULL)
return NULL;
......@@ -541,7 +553,9 @@ namespace AMDiS {
elinfo_stack[stack_used]->fillMacroInfo(traverse_mel);
info_stack[stack_used] = 0;
nb = i;
} else { /* goto other child */
} else {
// Goto other child.
stack2_used = stack_used + 1;
if (save_stack_used > stack2_used)
stack2_used++; /* go down one level in OLD hierarchy */
......@@ -551,24 +565,37 @@ namespace AMDiS {
if (stack_used >= stack_size-1)
enlargeTraverseStack();
i = 2 - info_stack[stack_used];
info_stack[stack_used] = i+1;
elinfo_stack[stack_used+1]->fillElInfo(i, elinfo_stack[stack_used]);
int i = 2 - info_stack[stack_used];
info_stack[stack_used] = i + 1;
int fillIthChild = i;
if (traverse_fill_flag.isSet(Mesh::CALL_REVERSE_MODE))
fillIthChild = 1 - fillIthChild;
elinfo_stack[stack_used+1]->fillElInfo(fillIthChild, elinfo_stack[stack_used]);
stack_used++;
info_stack[stack_used] = 0;
nb = 0;
}
elinfo = elinfo_stack[stack_used];
// === Second phase. ===
ElInfo *elinfo = elinfo_stack[stack_used];
el = elinfo->getElement();
while(el->getChild(0)) {
if (nb < 2) { /* go down one level in hierarchy */
if (stack_used >= stack_size-1)
while (el->getChild(0)) {
if (nb < 2) {
// Go down one level in hierarchy.
if (stack_used >= stack_size - 1)
enlargeTraverseStack();
info_stack[stack_used] = 2-nb;
elinfo_stack[stack_used+1]->fillElInfo(1 - nb, elinfo_stack[stack_used]);
info_stack[stack_used] = 2 - nb;
int fillIthChild = 1 - nb;
if (traverse_fill_flag.isSet(Mesh::CALL_REVERSE_MODE))
fillIthChild = 1 - fillIthChild;
elinfo_stack[stack_used + 1]->fillElInfo(fillIthChild, elinfo_stack[stack_used]);
stack_used++;
info_stack[stack_used] = 0;
elinfo = elinfo_stack[stack_used];
......@@ -576,9 +603,12 @@ namespace AMDiS {
nb = 3;
}
if (save_stack_used > stack2_used) { /* `refine' both el and el2 */
if (save_stack_used > stack2_used) {
// `refine' both el and el2.
TEST_EXIT_DBG(el->getChild(0))("invalid new refinement?\n");
int i = 0;
if (el->getDOF(0) == el2->getDOF(0))
i = save_info_stack[stack2_used] - 1;
else if (el->getDOF(1) == el2->getDOF(0))
......@@ -593,20 +623,22 @@ namespace AMDiS {
}
}
if (el->getChild(0) &&
if (el->getChild(0) &&
(el->getChild(i)->getDOF(1) == el->getDOF(nb) ||
traverse_mesh->associated(el->getChild(i)->getDOF(1, 0), el->getDOF(nb, 0))))
{ /* el->child[0] Kuni 22.08.96 */
nb = 1;
}
else {
nb = 2;
}