From 0addc7a4a3729d433d7c11c579f9c3c50b30b75a Mon Sep 17 00:00:00 2001 From: Thomas Witkowski <thomas.witkowski@gmx.de> Date: Fri, 19 Nov 2010 11:32:32 +0000 Subject: [PATCH] Code refactoring to make the implementation of mesh repartitioning easier. --- AMDiS/libtool | 46 +++--- AMDiS/src/AMDiS.h | 1 - AMDiS/src/ArhReader.cc | 2 +- AMDiS/src/CreatorMap.cc | 4 - AMDiS/src/ElementData.cc | 9 +- AMDiS/src/MeshStructure.cc | 22 +-- AMDiS/src/MeshStructure.h | 1 - AMDiS/src/PartitionElementData.h | 170 ---------------------- AMDiS/src/parallel/MeshDistributor.cc | 19 ++- AMDiS/src/parallel/ParMetisPartitioner.cc | 168 +++++---------------- AMDiS/src/parallel/ParMetisPartitioner.h | 27 +++- AMDiS/src/parallel/ParallelDebug.cc | 40 +++-- 12 files changed, 120 insertions(+), 389 deletions(-) delete mode 100644 AMDiS/src/PartitionElementData.h diff --git a/AMDiS/libtool b/AMDiS/libtool index f674d32d..730f91e3 100755 --- a/AMDiS/libtool +++ b/AMDiS/libtool @@ -51,32 +51,32 @@ build_old_libs=yes pic_mode=default # Whether or not to optimize for fast installation. -fast_install=yes +fast_install=needless # The host system. host_alias= -host=i686-redhat-linux-gnu +host=x86_64-unknown-linux-gnu host_os=linux-gnu # The build system. build_alias= -build=i686-redhat-linux-gnu +build=x86_64-unknown-linux-gnu build_os=linux-gnu # A sed program that does not truncate output. -SED="/bin/sed" +SED="/usr/bin/sed" # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e 1s/^X//" # A grep program that handles long lines. -GREP="/bin/grep" +GREP="/usr/bin/grep" # An ERE matcher. -EGREP="/bin/grep -E" +EGREP="/usr/bin/grep -E" # A literal string matcher. -FGREP="/bin/grep -F" +FGREP="/usr/bin/grep -F" # A BSD- or MS-compatible name lister. NM="/usr/bin/nm -B" @@ -85,7 +85,7 @@ NM="/usr/bin/nm -B" LN_S="ln -s" # What is the maximum length of a command? -max_cmd_len=98304 +max_cmd_len=1572864 # Object file suffix (normally "o"). objext=o @@ -128,7 +128,7 @@ old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib" old_postuninstall_cmds="" # A C compiler. -LTCC="gcc" +LTCC="/usr/lib64/mpi/gcc/openmpi//bin/mpicc" # LTCC compiler flags. LTCFLAGS="-g -O2" @@ -204,7 +204,7 @@ runpath_var=LD_RUN_PATH shlibpath_var=LD_LIBRARY_PATH # Is shlibpath searched before the hard-coded library search path? -shlibpath_overrides_runpath=no +shlibpath_overrides_runpath=yes # Format of library name prefix. libname_spec="lib\$name" @@ -233,10 +233,10 @@ finish_eval="" hardcode_into_libs=yes # Compile-time system search path for libraries. -sys_lib_search_path_spec="/u/backofen/adds/local/lib /usr/lib/gcc/i386-redhat-linux/4.1.2 /usr/lib /lib" +sys_lib_search_path_spec="/usr/lib64/gcc/x86_64-suse-linux/4.5 /usr/lib64 /lib64 /usr/x86_64-suse-linux/lib" # Run-time system search path for libraries. -sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/lib/mysql /usr/lib/octave-3.0.1 /usr/lib/qt-3.3/lib /usr/lib/qt4/lib /usr/lib/xulrunner-1.9.2 " +sys_lib_dlsearch_path_spec="/lib /usr/lib /usr/X11R6/lib64/Xaw3d /usr/X11R6/lib64 /usr/lib64/Xaw3d /usr/X11R6/lib/Xaw3d /usr/X11R6/lib /usr/lib/Xaw3d /usr/x86_64-suse-linux/lib /usr/local/lib /opt/kde3/lib /lib64 /lib /usr/lib64 /usr/lib /usr/local/lib64 /opt/kde3/lib64 /usr/lib64/graphviz /usr/lib64/graphviz/sharp /usr/lib64/graphviz/java /usr/lib64/graphviz/perl /usr/lib64/graphviz/php /usr/lib64/graphviz/ocaml /usr/lib64/graphviz/python /usr/lib64/graphviz/lua /usr/lib64/graphviz/tcl /usr/lib64/graphviz/guile /usr/lib64/graphviz/ruby /usr/lib64/octave-3.2.4 " # Whether dlopen is supported. dlopen_support=unknown @@ -253,13 +253,13 @@ striplib="strip --strip-unneeded" # The linker used to build libraries. -LD="/usr/bin/ld" +LD="/usr/x86_64-suse-linux/bin/ld -m elf_x86_64" # Commands used to build an old-style archive. old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib" # A language specific compiler. -CC="gcc" +CC="/usr/lib64/mpi/gcc/openmpi//bin/mpicc" # Is the compiler the GNU compiler? with_gcc=yes @@ -274,7 +274,7 @@ wl="-Wl," pic_flag=" -fPIC -DPIC" # Compiler flag to prevent dynamic linking. -link_static_flag="-static" +link_static_flag="" # Does compiler simultaneously support -c and -o options? compiler_c_o="yes" @@ -8908,13 +8908,13 @@ build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. -LD="/usr/bin/ld" +LD="/usr/x86_64-suse-linux/bin/ld -m elf_x86_64" # Commands used to build an old-style archive. old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib" # A language specific compiler. -CC="g++" +CC="/usr/lib64/mpi/gcc/openmpi//bin/mpicxx" # Is the compiler the GNU compiler? with_gcc=yes @@ -8929,7 +8929,7 @@ wl="-Wl," pic_flag=" -fPIC -DPIC" # Compiler flag to prevent dynamic linking. -link_static_flag="-static" +link_static_flag="" # Does compiler simultaneously support -c and -o options? compiler_c_o="yes" @@ -9039,17 +9039,17 @@ file_list_spec="" hardcode_action=immediate # The directories searched by this compiler when creating a shared library. -compiler_lib_search_dirs="/u/backofen/adds/local/lib /usr/lib/gcc/i386-redhat-linux/4.1.2 /usr/lib/gcc/i386-redhat-linux/4.1.2 /usr/lib/gcc/i386-redhat-linux/4.1.2/../../.." +compiler_lib_search_dirs="/usr/lib64/mpi/gcc/openmpi/lib64 /usr/lib64/gcc/x86_64-suse-linux/4.5 /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib64 /lib/../lib64 /usr/lib/../lib64 /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/lib /usr/lib64/gcc/x86_64-suse-linux/4.5/../../.." # Dependencies to place before and after the objects being linked to # create a shared library. -predep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginS.o" -postdep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/crtendS.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o" +predep_objects="/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.5/crtbeginS.o" +postdep_objects="/usr/lib64/gcc/x86_64-suse-linux/4.5/crtendS.o /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib64/crtn.o" predeps="" -postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s" +postdeps="-lmpi_cxx -lmpi -lopen-rte -lopen-pal -ldl -lnsl -lutil -ldl -lstdc++ -lm -lgcc_s -lpthread -lc -lgcc_s" # The library search path used internally by the compiler when linking # a shared library. -compiler_lib_search_path="-L/u/backofen/adds/local/lib -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.." +compiler_lib_search_path="-L/usr/lib64/mpi/gcc/openmpi/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.5 -L/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.5/../../.." # ### END LIBTOOL TAG CONFIG: CXX diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h index 1734ff92..74da8b19 100644 --- a/AMDiS/src/AMDiS.h +++ b/AMDiS/src/AMDiS.h @@ -65,7 +65,6 @@ #include "OperatorTerm.h" #include "Parameters.h" #include "Parametric.h" -#include "PartitionElementData.h" #include "PeriodicMap.h" #include "PeriodicBC.h" #include "PngWriter.h" diff --git a/AMDiS/src/ArhReader.cc b/AMDiS/src/ArhReader.cc index 912cd865..1709c988 100644 --- a/AMDiS/src/ArhReader.cc +++ b/AMDiS/src/ArhReader.cc @@ -51,7 +51,7 @@ namespace AMDiS { MeshStructure elementStructure; elementStructure.init(structureCode, codeSize); - elementStructure.fitMeshToStructure(mesh, refManager, false, + elementStructure.fitMeshToStructure(mesh, refManager, false, elIndex, ignoreFinerMesh); uint32_t nValuesPerVector = 0; diff --git a/AMDiS/src/CreatorMap.cc b/AMDiS/src/CreatorMap.cc index fbe1bdbd..4e180164 100644 --- a/AMDiS/src/CreatorMap.cc +++ b/AMDiS/src/CreatorMap.cc @@ -11,7 +11,6 @@ #include "LeafData.h" #include "SurfaceRegion_ED.h" #include "ElementRegion_ED.h" -#include "PartitionElementData.h" #include "DOFMatrix.h" #include "UmfPackSolver.h" #include "time/RosenbrockMethod.h" @@ -120,9 +119,6 @@ namespace AMDiS { creator = new ElementRegion_ED::Creator; addCreator("ElementRegion_ED", creator); - - creator = new PartitionElementData::Creator; - addCreator("PartitionElementData", creator); } diff --git a/AMDiS/src/ElementData.cc b/AMDiS/src/ElementData.cc index 892a7e3e..ee81220a 100644 --- a/AMDiS/src/ElementData.cc +++ b/AMDiS/src/ElementData.cc @@ -1,5 +1,5 @@ #include "ElementData.h" -#include "PartitionElementData.h" + namespace AMDiS { void ElementData::coarsenElementData(Element* parent, @@ -8,13 +8,6 @@ namespace AMDiS { int elTypeParent) { if (decorated) { - PartitionElementData* ped = NULL; - ped = dynamic_cast<PartitionElementData*>(thisChild->getElementData(PARTITION_ED)); - ped = NULL; - ped = dynamic_cast<PartitionElementData*>(otherChild->getElementData(PARTITION_ED)); - ped = NULL; - ped = dynamic_cast<PartitionElementData*> (parent->getElementData(PARTITION_ED)); - decorated->coarsenElementData(parent, thisChild, otherChild, elTypeParent); delete decorated; decorated = NULL; diff --git a/AMDiS/src/MeshStructure.cc b/AMDiS/src/MeshStructure.cc index e499031f..1c8f656b 100644 --- a/AMDiS/src/MeshStructure.cc +++ b/AMDiS/src/MeshStructure.cc @@ -1,6 +1,5 @@ #include "MeshStructure.h" #include "MeshStructure_ED.h" -#include "PartitionElementData.h" #include "Mesh.h" #include "Element.h" #include "Traverse.h" @@ -226,7 +225,6 @@ namespace AMDiS { void MeshStructure::fitMeshToStructure(Mesh *mesh, RefinementManager *manager, - bool checkPartition, bool debugMode, int macroElIndex, bool ignoreFinerMesh) @@ -267,23 +265,9 @@ namespace AMDiS { cont = skipBranch(structure); structure->commit(); - bool decorate = true; - if (checkPartition) { - PartitionElementData *partitionData = dynamic_cast<PartitionElementData*> - (element->getElementData(PARTITION_ED)); - TEST_EXIT_DBG(partitionData)("no partition element data\n"); - PartitionStatus status = partitionData->getPartitionStatus(); - if (debugMode == false && (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; - } + MeshStructure_ED *elData = new MeshStructure_ED(element->getElementData()); + elData->setStructure(structure); + element->setElementData(elData); } else { cont = nextElement(); } diff --git a/AMDiS/src/MeshStructure.h b/AMDiS/src/MeshStructure.h index c50bb7df..9c202957 100644 --- a/AMDiS/src/MeshStructure.h +++ b/AMDiS/src/MeshStructure.h @@ -109,7 +109,6 @@ namespace AMDiS { */ void fitMeshToStructure(Mesh *mesh, RefinementManager *manager, - bool checkPartition = false, bool debugMode = false, int macroElIndex = -1, bool ignoreFinerMesh = false); diff --git a/AMDiS/src/PartitionElementData.h b/AMDiS/src/PartitionElementData.h deleted file mode 100644 index 8caf7c9d..00000000 --- a/AMDiS/src/PartitionElementData.h +++ /dev/null @@ -1,170 +0,0 @@ -// ============================================================================ -// == == -// == AMDiS - Adaptive multidimensional simulations == -// == == -// ============================================================================ -// == == -// == TU Dresden == -// == == -// == Institut für Wissenschaftliches Rechnen == -// == Zellescher Weg 12-14 == -// == 01069 Dresden == -// == germany == -// == == -// ============================================================================ -// == == -// == https://gforge.zih.tu-dresden.de/projects/amdis/ == -// == == -// ============================================================================ - -/** \file PartitionElementData.h */ - -#ifndef AMDIS_PARTITIONELEMENTDATA_H -#define AMDIS_PARTITIONELEMENTDATA_H - -#include "Element.h" -#include "ElementData.h" -#include "FixVec.h" -#include "Serializer.h" - -namespace AMDiS { - - const int PARTITION_ED = 7; - - enum PartitionStatus { - UNDEFINED = -1, - IN = 0, - OVERLAP = 1, - OUT = 2 - }; - - class PartitionElementData : public ElementData - { - public: - inline bool isOfType(int typeID) const - { - if (typeID == PARTITION_ED) - return true; - return false; - } - - class Creator : public CreatorInterface<ElementData> - { - public: - ElementData* create() - { - return new PartitionElementData; - } - }; - - PartitionElementData(ElementData *decorated = NULL) - : ElementData(decorated), - status(UNDEFINED), - level(0) - {} - - ~PartitionElementData() - {} - - bool refineElementData(Element* parent, - Element* child1, - Element* child2, - int elType) - { - ElementData::refineElementData(parent, child1, child2, elType); - - PartitionElementData *child1Data = - new PartitionElementData(child1->getElementData()); - PartitionElementData *child2Data = - new PartitionElementData(child2->getElementData()); - child1Data->setPartitionStatus(status); - child2Data->setPartitionStatus(status); - child1Data->setLevel(level + 1); - child2Data->setLevel(level + 1); - child1->setElementData(child1Data); - child2->setElementData(child2Data); - return false; - } - - ElementData *clone() const - { - PartitionElementData *newObj = new PartitionElementData; - newObj->decorated = ElementData::clone(); - return newObj; - } - - inline std::string getTypeName() const - { - return "PartitionElementData"; - } - - inline const int getTypeID() const - { - return PARTITION_ED; - } - - void serialize(std::ostream& out) - { - ElementData::serialize(out); - SerUtil::serialize(out, status); - SerUtil::serialize(out, level); - } - - void deserialize(std::istream& in) - { - ElementData::deserialize(in); - SerUtil::deserialize(in, status); - SerUtil::deserialize(in, level); - } - - inline void setPartitionStatus(PartitionStatus s) - { - status = s; - } - - inline PartitionStatus getPartitionStatus() - { - return status; - } - - inline void setLevel(int l) - { - level = l; - } - - inline int getLevel() - { - return level; - } - - void descend(Element *element) - { - if (!element->isLeaf()) { - Element *child0 = element->getChild(0); - Element *child1 = element->getChild(1); - - // get partition data - PartitionElementData *child0Data = dynamic_cast<PartitionElementData*> - (child0->getElementData(PARTITION_ED)); - PartitionElementData *child1Data = dynamic_cast<PartitionElementData*> - (child1->getElementData(PARTITION_ED)); - - TEST_EXIT(child0Data && child1Data)("no partition data\n"); - - child0Data->setPartitionStatus(this->getPartitionStatus()); - child1Data->setPartitionStatus(this->getPartitionStatus()); - - child0Data->descend(child0); - child1Data->descend(child1); - } - } - - protected: - PartitionStatus status; - - int level; - }; - -} - -#endif diff --git a/AMDiS/src/parallel/MeshDistributor.cc b/AMDiS/src/parallel/MeshDistributor.cc index a2705100..c0d78f4a 100644 --- a/AMDiS/src/parallel/MeshDistributor.cc +++ b/AMDiS/src/parallel/MeshDistributor.cc @@ -14,7 +14,6 @@ #include "ElInfo.h" #include "Element.h" #include "MacroElement.h" -#include "PartitionElementData.h" #include "DOFMatrix.h" #include "DOFVector.h" #include "SystemVector.h" @@ -112,7 +111,6 @@ namespace AMDiS { MSG("Skip write part mesh!\n"); } } - ParallelDebug::testAllElements(*this); #endif @@ -145,6 +143,7 @@ namespace AMDiS { #if (DEBUG != 0) MSG("AMDiS runs in debug mode, so make some test ...\n"); + ParallelDebug::testAllElements(*this); debug::testSortedDofs(mesh, elMap); ParallelDebug::testInteriorBoundary(*this); ParallelDebug::testCommonDofs(*this, true); @@ -944,7 +943,7 @@ namespace AMDiS { partitioner->partition(&elemWeights, INITIAL); } else { oldPartitionVec = partitionVec; - partitioner->partition(&elemWeights, ADAPTIVE_REPART, 100.0 /*0.000001*/); + partitioner->partition(&elemWeights, ADAPTIVE_REPART, 1000.0); } partitioner->fillCoarsePartitionVec(&partitionVec); @@ -1003,6 +1002,10 @@ namespace AMDiS { partitioner->useLocalGlobalDofMap(&mapLocalGlobalDofs); partitionMesh(); +#if (DEBUG != 0) + ParallelDebug::testAllElements(*this); +#endif + MSG("DONE\n"); } @@ -1412,13 +1415,9 @@ namespace AMDiS { std::set<MacroElement*> macrosToRemove; for (std::deque<MacroElement*>::iterator it = mesh->firstMacroElement(); it != mesh->endOfMacroElements(); - ++it) { - PartitionElementData *partitionData = - dynamic_cast<PartitionElementData*> - ((*it)->getElement()->getElementData(PARTITION_ED)); - if (partitionData->getPartitionStatus() != IN) - macrosToRemove.insert(*it); - } + ++it) + if (partitioner->getElementInRank()[(*it)->getIndex()] == false) + macrosToRemove.insert(*it); mesh->removeMacroElements(macrosToRemove, feSpace); } diff --git a/AMDiS/src/parallel/ParMetisPartitioner.cc b/AMDiS/src/parallel/ParMetisPartitioner.cc index 1fc8d5b2..b92f6570 100644 --- a/AMDiS/src/parallel/ParMetisPartitioner.cc +++ b/AMDiS/src/parallel/ParMetisPartitioner.cc @@ -5,13 +5,13 @@ #include "ElInfo.h" #include "Element.h" #include "FixVec.h" -#include "PartitionElementData.h" #include "DOFVector.h" #include "mpi.h" namespace AMDiS { ParMetisMesh::ParMetisMesh(Mesh *mesh, MPI::Intracomm *comm, + std::map<int, bool>& elementInRank, std::map<DegreeOfFreedom, DegreeOfFreedom> *mapLocalGlobal) : dim(mesh->getDim()), nElements(0), @@ -25,15 +25,9 @@ namespace AMDiS { int dow = Global::getGeo(WORLD); TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); + ElInfo *elInfo = stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { - // get partition data - PartitionElementData *partitionData = dynamic_cast<PartitionElementData*> - (elInfo->getElement()->getElementData(PARTITION_ED)); - - if (partitionData && - partitionData->getPartitionStatus() == IN && - partitionData->getLevel() == 0) + if (elementInRank[elInfo->getElement()->getIndex()]) elementCounter++; elInfo = stack.traverseNext(elInfo); @@ -73,20 +67,13 @@ namespace AMDiS { elementCounter = 0; - elInfo = stack.traverseFirst(mesh, -1, - Mesh::CALL_EVERY_EL_PREORDER | Mesh::FILL_COORDS); + elInfo = stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL | Mesh::FILL_COORDS); while (elInfo) { Element *element = elInfo->getElement(); int index = element->getIndex(); - // get partition data - PartitionElementData *partitionData = dynamic_cast<PartitionElementData*> - (element->getElementData(PARTITION_ED)); - // if element in partition - if (partitionData && - partitionData->getPartitionStatus() == IN && - partitionData->getLevel() == 0) { + if (elementInRank[index]) { // remember index setParMetisIndex(index, elementCounter); setAMDiSIndex(elementCounter, index); @@ -117,6 +104,7 @@ namespace AMDiS { elementCounter++; } + elInfo = stack.traverseNext(elInfo); } } @@ -157,8 +145,6 @@ namespace AMDiS { ncommonnodes = parMetisMesh->getDim(); MPI_Comm tmpComm = MPI_Comm(*comm); - int mpiRank = MPI::COMM_WORLD.Get_rank(); - int mpiSize = MPI::COMM_WORLD.Get_size(); ParMETIS_V3_Mesh2Dual(parMetisMesh->getElementDist(), parMetisMesh->getElementPtr(), @@ -178,18 +164,6 @@ namespace AMDiS { } - void ParMetisPartitioner::deletePartitionData() - { - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); - while (elInfo) { - Element *element = elInfo->getElement(); - element->deleteElementData(PARTITION_ED); - elInfo = stack.traverseNext(elInfo); - } - } - - void ParMetisPartitioner::createPartitionData() { FUNCNAME("ParMetrisPartitioner::createPartitionData()"); @@ -201,25 +175,20 @@ namespace AMDiS { // === Create initial partitioning of the AMDiS mesh. === + elementInRank.clear(); + TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); + ElInfo *elInfo = stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { Element *element = elInfo->getElement(); - TEST_EXIT(element->getElementData(PARTITION_ED) == NULL) - ("mesh already partitioned\n"); - - PartitionElementData *elData = - new PartitionElementData(element->getElementData()); - element->setElementData(elData); - if ((element->getIndex() >= mpiRank * elPerRank && element->getIndex() < (mpiRank + 1) * elPerRank) || (element->getIndex() >= mpiSize * elPerRank && mpiRank == mpiSize - 1)) - elData->setPartitionStatus(IN); + elementInRank[element->getIndex()] = true; else - elData->setPartitionStatus(UNDEFINED); + elementInRank[element->getIndex()] = false; elInfo = stack.traverseNext(elInfo); } @@ -238,7 +207,8 @@ namespace AMDiS { if (parMetisMesh) delete parMetisMesh; - parMetisMesh = new ParMetisMesh(mesh, mpiComm, mapLocalGlobal); + TEST_EXIT(elementInRank.size() != 0)("Should not happen!\n"); + parMetisMesh = new ParMetisMesh(mesh, mpiComm, elementInRank, mapLocalGlobal); int nElements = parMetisMesh->getNumElements(); @@ -249,20 +219,11 @@ namespace AMDiS { float *ptr_floatWgts = floatWgts; TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); + ElInfo *elInfo = stack.traverseFirst(mesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { - Element *element = elInfo->getElement(); - - // get partition data - PartitionElementData *partitionData = dynamic_cast<PartitionElementData*> - (element->getElementData(PARTITION_ED)); - - if (partitionData && - partitionData->getPartitionStatus() == IN && - partitionData->getLevel() == 0) { - - int index = element->getIndex(); + int index = elInfo->getElement()->getIndex(); + if (elementInRank[index]) { // get weight float wgt = static_cast<float>((*elemWeights)[index]); maxWgt = max(wgt, maxWgt); @@ -306,7 +267,7 @@ namespace AMDiS { MPI_Comm tmpComm = MPI_Comm(*mpiComm); - switch(mode) { + switch (mode) { case INITIAL: ParMETIS_V3_PartKway(parMetisMesh->getElementDist(), parMetisGraph.getXAdj(), @@ -346,6 +307,7 @@ namespace AMDiS { &edgecut, part, &tmpComm); + delete [] vsize; } break; @@ -365,6 +327,7 @@ namespace AMDiS { &edgecut, part, &tmpComm); + break; default: ERROR_EXIT("unknown partitioning mode\n"); @@ -392,7 +355,7 @@ namespace AMDiS { // update ParMETIS mesh to new partitioning if (!parMetisMesh) - parMetisMesh = new ParMetisMesh(mesh, mpiComm, mapLocalGlobal); + parMetisMesh = new ParMetisMesh(mesh, mpiComm, elementInRank, mapLocalGlobal); int mpiRank = mpiComm->Get_rank(); int mpiSize = mpiComm->Get_size(); @@ -438,12 +401,13 @@ namespace AMDiS { for (int i = 0; i < mpiSize; i++) nPartitionElements[i] = 0; for (int i = 0; i < nElements; i++) - nPartitionElements[part[i]]++; + nPartitionElements[part[i]]++; // collect number of partition elements from all ranks for this rank int *nRankElements = new int[mpiSize]; mpiComm->Alltoall(nPartitionElements, 1, MPI_INT, nRankElements, 1, MPI_INT); + // sum up partition elements over all ranks int *sumPartitionElements = new int[mpiSize]; mpiComm->Allreduce(nPartitionElements, sumPartitionElements, mpiSize, @@ -458,12 +422,17 @@ namespace AMDiS { int *partitionElements = new int[nElements]; int **partitionPtr = new int*[mpiSize]; - for (int i = 0; i < mpiSize; i++) + sendElements.resize(mpiSize); + for (int i = 0; i < mpiSize; i++) { partitionPtr[i] = partitionElements + bufferOffset[i]; + sendElements[i].clear(); + } for (int i = 0; i < nElements; i++) { int partition = part[i]; int amdisIndex = parMetisMesh->getAMDiSIndex(i); + + sendElements[partition].push_back(amdisIndex); *(partitionPtr[partition]) = amdisIndex; ++(partitionPtr[partition]); } @@ -484,37 +453,23 @@ namespace AMDiS { recvBufferOffset, MPI_INT); + TEST_EXIT(elementInRank.size() != 0)("Should not happen!\n"); + for (std::map<int, bool>::iterator it = elementInRank.begin(); + it != elementInRank.end(); ++it) + elementInRank[it->first] = false; // Create map which stores for each element index on ther partitioning level // if the element is in the partition of this rank. - std::map<int, bool> elementInPartition; + recvElements.resize(mpiSize); for (int i = 0; i < mpiSize; i++) { + recvElements[i].clear(); + int *rankStart = rankElements + recvBufferOffset[i]; int *rankEnd = rankStart + nRankElements[i]; - for (int *rankPtr = rankStart; rankPtr < rankEnd; ++rankPtr) - elementInPartition[*rankPtr] = true; - } - - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); - while (elInfo) { - Element *element = elInfo->getElement(); - - // get partition data - PartitionElementData *partitionData = dynamic_cast<PartitionElementData*> - (element->getElementData(PARTITION_ED)); - - if (partitionData && partitionData->getLevel() == 0) { - int amdisIndex = element->getIndex(); - if (elementInPartition[amdisIndex]) - partitionData->setPartitionStatus(IN); - else - partitionData->setPartitionStatus(OUT); - - descendPartitionData(element); + for (int *rankPtr = rankStart; rankPtr < rankEnd; ++rankPtr) { + elementInRank[*rankPtr] = true; + recvElements[i].push_back(*rankPtr); } - - elInfo = stack.traverseNext(elInfo); } delete parMetisMesh; @@ -530,51 +485,4 @@ namespace AMDiS { delete [] recvBufferOffset; } - - void ParMetisPartitioner::descendPartitionData(Element *element) - { - FUNCNAME("ParMetisPartitioner::descendPartitionData()"); - - if (!element->isLeaf()) { - Element *child0 = element->getChild(0); - Element *child1 = element->getChild(1); - - // get partition data - PartitionElementData *parentData = dynamic_cast<PartitionElementData*> - (element->getElementData(PARTITION_ED)); - PartitionElementData *child0Data = dynamic_cast<PartitionElementData*> - (child0->getElementData(PARTITION_ED)); - PartitionElementData *child1Data = dynamic_cast<PartitionElementData*> - (child1->getElementData(PARTITION_ED)); - - TEST_EXIT(parentData && child0Data && child1Data)("no partition data\n"); - - child0Data->setPartitionStatus(parentData->getPartitionStatus()); - child1Data->setPartitionStatus(parentData->getPartitionStatus()); - - descendPartitionData(child0); - descendPartitionData(child1); - } - } - - - void ParMetisPartitioner::fillLeafPartitionVec(std::map<int, int> *coarseVec, - std::map<int, int> *fineVec) - { - int partition = -1; - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); - while (elInfo) { - Element *element = elInfo->getElement(); - PartitionElementData *partitionData = dynamic_cast<PartitionElementData*> - (element->getElementData(PARTITION_ED)); - if (partitionData) { - if (partitionData->getLevel() == 0) - partition = (*(coarseVec))[element->getIndex()]; - if (element->isLeaf()) - (*(fineVec))[element->getIndex()] = partition; - } - elInfo = stack.traverseNext(elInfo); - } - } } diff --git a/AMDiS/src/parallel/ParMetisPartitioner.h b/AMDiS/src/parallel/ParMetisPartitioner.h index c860fb29..e9ca5f5b 100644 --- a/AMDiS/src/parallel/ParMetisPartitioner.h +++ b/AMDiS/src/parallel/ParMetisPartitioner.h @@ -46,6 +46,7 @@ namespace AMDiS { { public: ParMetisMesh(Mesh *mesh, MPI::Intracomm *comm, + std::map<int, bool>& elementInRank, std::map<DegreeOfFreedom, DegreeOfFreedom> *mapLocalGlobal); ~ParMetisMesh(); @@ -185,27 +186,35 @@ namespace AMDiS { */ void fillCoarsePartitionVec(std::map<int, int> *partitionVec); - void fillLeafPartitionVec(std::map<int, int> *coarseVec, - std::map<int, int> *fineVec); - /* \brief * Creates an initial paritioning of the AMDiS mesh by seting the partition status * of all elements to either IN or UNDEFINED. */ void createPartitionData(); - void deletePartitionData(); - void useLocalGlobalDofMap(std::map<DegreeOfFreedom, DegreeOfFreedom> *m) { mapLocalGlobal = m; } + std::map<int, bool>& getElementInRank() + { + return elementInRank; + } + + std::vector<std::vector<int> >& getRecvElements() + { + return recvElements; + } + + std::vector<std::vector<int> >& getSendElements() + { + return sendElements; + } + protected: void distributePartitioning(int *part); - void descendPartitionData(Element *element); - protected: Mesh *mesh; @@ -214,6 +223,10 @@ namespace AMDiS { ParMetisMesh *parMetisMesh; std::map<DegreeOfFreedom, DegreeOfFreedom> *mapLocalGlobal; + + std::map<int, bool> elementInRank; + + std::vector<std::vector<int> > recvElements, sendElements; }; } diff --git a/AMDiS/src/parallel/ParallelDebug.cc b/AMDiS/src/parallel/ParallelDebug.cc index 15289a95..f5af359b 100644 --- a/AMDiS/src/parallel/ParallelDebug.cc +++ b/AMDiS/src/parallel/ParallelDebug.cc @@ -1,6 +1,5 @@ #include "ParallelDebug.h" #include "MeshDistributor.h" -#include "PartitionElementData.h" #include "ProblemVec.h" #include "DOFVector.h" #include "FixVec.h" @@ -318,33 +317,44 @@ namespace AMDiS { TEST_EXIT(foundError == 0)("Error found on at least on rank!\n"); } + void ParallelDebug::testAllElements(MeshDistributor &pdb) { FUNCNAME("ParallelDebug::testAllElements()"); + std::set<int> macroElements; + int minElementIndex = std::numeric_limits<int>::max(); + int maxElementIndex = std::numeric_limits<int>::min(); + TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(pdb.mesh, -1, Mesh::CALL_LEAF_EL); + ElInfo *elInfo = stack.traverseFirst(pdb.mesh, 0, Mesh::CALL_EL_LEVEL); while (elInfo) { - Element *element = elInfo->getElement(); - PartitionElementData *partitionData = - dynamic_cast<PartitionElementData*>(element->getElementData(PARTITION_ED)); + int elIndex = elInfo->getElement()->getIndex(); + minElementIndex = std::min(minElementIndex, elIndex); + maxElementIndex = std::max(maxElementIndex, elIndex); + macroElements.insert(elInfo->getElement()->getIndex()); + elInfo = stack.traverseNext(elInfo); + } + + int globalMinIndex, globalMaxIndex; + pdb.mpiComm.Allreduce(&minElementIndex, &globalMinIndex, 1, MPI_INT, MPI_MIN); + pdb.mpiComm.Allreduce(&maxElementIndex, &globalMaxIndex, 1, MPI_INT, MPI_MAX); - int sendId = 0; - if (partitionData->getPartitionStatus() == IN) - sendId = 1; + TEST_EXIT(globalMinIndex == 0)("No macro element with index 0!\n"); + for (int i = 0; i <= globalMaxIndex; i++) { + int sendId = macroElements.count(i); int recvId = 0; pdb.mpiComm.Allreduce(&sendId, &recvId, 1, MPI_INT, MPI_SUM); if (recvId != 1 && pdb.mpiRank == 0) { - if (recvId == 0) - ERROR_EXIT("Element %d has no member partition!\n", element->getIndex()); + if (recvId == 0) { + ERROR_EXIT("Element %d has no member partition!\n", i); + } - if (recvId > 1) - ERROR_EXIT("Element %d is member of more than pne partition!\n", - element->getIndex()); + if (recvId > 1) { + ERROR_EXIT("Element %d is member of more than pne partition!\n", i); + } } - - elInfo = stack.traverseNext(elInfo); } } -- GitLab