#include "MeshStructure.h" #include "MeshStructure_ED.h" #include "PartitionElementData.h" #include "Mesh.h" #include "Element.h" #include "Traverse.h" #include "ElInfo.h" #include "RefinementManager.h" #include "mpi.h" namespace AMDiS { const int MeshStructure::unsignedLongSize_ = sizeof(unsigned long int) * 8; void MeshStructure::insertElement(bool isLeaf) { // overflow? -> next index if(pos_ >= unsignedLongSize_) { code_.push_back(currentCode_); pos_ = 0; currentCode_ = 0; } // insert element in binary code if(!isLeaf) { unsigned long int one = 1; currentCode_ += (one << pos_); } pos_++; numElements_++; } void MeshStructure::clear() { currentCode_ = 0; code_.resize(0); pos_ = 0; numElements_ = 0; currentElement_ = 0; } void MeshStructure::init(Mesh *mesh) { clear(); TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); while(elInfo) { insertElement(elInfo->getElement()->isLeaf()); elInfo = stack.traverseNext(elInfo); } commit(); } void MeshStructure::reset() { currentIndex_ = 0; currentCode_ = code_[0]; pos_ = 0; currentElement_ = 0; } bool MeshStructure::nextElement(MeshStructure *insert) { if(insert) { insert->insertElement(isLeafElement()); } pos_++; currentElement_++; if(currentElement_ >= numElements_) return false; if(pos_ >= unsignedLongSize_) { currentIndex_++; TEST_EXIT_DBG(currentIndex_ < static_cast(code_.size())) ("end of structure reached\n"); pos_ = 0; currentCode_ = code_[currentIndex_]; } else { currentCode_ >>= 1; } return true; } bool MeshStructure::skipBranch(MeshStructure *insert) { if(isLeafElement()) { return nextElement(insert); } else { bool cont = nextElement(insert); cont = skipBranch(insert); // left branch TEST_EXIT_DBG(cont)("invalid structure\n"); cont = skipBranch(insert); // righ branch return cont; } } void MeshStructure::merge(MeshStructure *structure1, MeshStructure *structure2, MeshStructure *result) { result->clear(); structure1->reset(); structure2->reset(); bool cont = true; while(cont) { bool cont1, cont2; if(structure1->isLeafElement() == structure2->isLeafElement()) { cont1 = structure1->nextElement(result); cont2 = structure2->nextElement(); } else { if(structure1->isLeafElement()) { cont1 = structure1->nextElement(); cont2 = structure2->skipBranch(result); } else { cont1 = structure1->skipBranch(result); cont2 = structure2->nextElement(); } } TEST_EXIT_DBG(cont1 == cont2)("structures don't match\n"); cont = cont1; } result->commit(); } void MeshStructure::fitMeshToStructure(Mesh *mesh, RefinementManager *manager, bool checkPartition) { FUNCNAME("MeshStructure::fitMeshToStructure()"); TraverseStack stack; ElInfo *elInfo; bool cont = true; // decorate leaf data reset(); elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); while(elInfo) { TEST_EXIT_DBG(cont)("unexpected structure code end!\n"); Element *element = elInfo->getElement(); if(isLeafElement()) { TEST_EXIT_DBG(element->isLeaf())("mesh finer than code\n"); }; if(element->isLeaf() && !isLeafElement()) { MeshStructure *structure = NEW MeshStructure(); cont = skipBranch(structure); structure->commit(); bool decorate = true; if(checkPartition) { PartitionElementData *partitionData = dynamic_cast (element->getElementData(PARTITION_ED)); TEST_EXIT_DBG(partitionData)("no partition element data\n"); PartitionStatus status = partitionData->getPartitionStatus(); if(status == OUT || status == UNDEFINED) { decorate = false; } } if(decorate) { MeshStructure_ED *elData = NEW MeshStructure_ED(element->getElementData()); elData->setStructure(structure); element->setElementData(elData); } else { DELETE structure; } } else { cont = nextElement(); } elInfo = stack.traverseNext(elInfo); } // refine mesh bool finished; do { finished = true; elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); while(elInfo) { Element *element = elInfo->getElement(); if(element->getElementData(MESH_STRUCTURE) != NULL) { element->setMark(1); finished = false; } else { element->setMark(0); } elInfo = stack.traverseNext(elInfo); } manager->refineMesh(mesh); } while(!finished); } }