diff --git a/AMDiS/libtool b/AMDiS/libtool index e6b2b7bebb4f36988e339a8ec585586dda4ca80d..7a44f979a6609656f23a9c6b42b6696cca43c6cd 100755 --- a/AMDiS/libtool +++ b/AMDiS/libtool @@ -44,7 +44,7 @@ available_tags=" CXX F77" # ### BEGIN LIBTOOL CONFIG -# Libtool was configured on host deimos103: +# Libtool was configured on host p2q071: # Shell to use when invoking shell scripts. SHELL="/bin/sh" @@ -82,13 +82,13 @@ AR="ar" AR_FLAGS="cru" # A C compiler. -LTCC="gcc" +LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc" # LTCC compiler flags. LTCFLAGS="-g -O2" # A language-specific compiler. -CC="gcc" +CC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc" # Is the compiler the GNU C compiler? with_gcc=yes @@ -171,7 +171,7 @@ dlopen_self=unknown dlopen_self_static=unknown # Compiler flag to prevent dynamic linking. -link_static_flag="-static" +link_static_flag="" # Compiler flag to turn off builtin functions. no_builtin_flag=" -fno-builtin" @@ -6760,7 +6760,7 @@ build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` # End: # ### BEGIN LIBTOOL TAG CONFIG: CXX -# Libtool was configured on host deimos103: +# Libtool was configured on host p2q071: # Shell to use when invoking shell scripts. SHELL="/bin/sh" @@ -6798,13 +6798,13 @@ AR="ar" AR_FLAGS="cru" # A C compiler. -LTCC="gcc" +LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc" # LTCC compiler flags. LTCFLAGS="-g -O2" # A language-specific compiler. -CC="g++" +CC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpiCC" # Is the compiler the GNU C compiler? with_gcc=yes @@ -6887,7 +6887,7 @@ dlopen_self=unknown dlopen_self_static=unknown # Compiler flag to prevent dynamic linking. -link_static_flag="-static" +link_static_flag="" # Compiler flag to turn off builtin functions. no_builtin_flag=" -fno-builtin" @@ -6954,11 +6954,11 @@ predeps="" # Dependencies to place after the objects being linked to create a # shared library. -postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s" +postdeps="-lmpi_cxx -lmpi -lopen-rte -lopen-pal -libverbs -lrt -lnuma -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/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.." +compiler_lib_search_path="-L/usr/lib64 -L/licsoft/libraries/openmpi/1.2.6/64bit/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.." # Method to check whether dependent libraries are shared objects. deplibs_check_method="pass_all" @@ -7065,7 +7065,7 @@ include_expsyms="" # ### BEGIN LIBTOOL TAG CONFIG: F77 -# Libtool was configured on host deimos103: +# Libtool was configured on host p2q071: # Shell to use when invoking shell scripts. SHELL="/bin/sh" @@ -7103,7 +7103,7 @@ AR="ar" AR_FLAGS="cru" # A C compiler. -LTCC="gcc" +LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc" # LTCC compiler flags. LTCFLAGS="-g -O2" diff --git a/AMDiS/src/Element.cc b/AMDiS/src/Element.cc index e251c974cecbbaf66c2f249cd25cfde5546c204a..62c5618f3f70f67e96fddadecbcf25d28e06d0a4 100644 --- a/AMDiS/src/Element.cc +++ b/AMDiS/src/Element.cc @@ -566,71 +566,4 @@ namespace AMDiS { return result; } - bool fitElementToMeshCode(RefinementManager *refineManager, - MeshStructure &code, - Element *el, - int ithSide, - int elType) - { - FUNCNAME("fitElementToMeshCode()"); - - if (code.empty()) - return false; - - int s1 = el->getSideOfChild(0, ithSide, elType); - int s2 = el->getSideOfChild(1, ithSide, elType); - - TEST_EXIT_DBG(s1 != -1 || s2 != -1)("This should not happen!\n"); - - if (s1 != -1 && s2 != -1) - return fitElementToMeshCode2(refineManager, code, el, ithSide, elType); - - if (el->isLeaf()) { - if (code.getNumElements() == 1 && code.isLeafElement()) - return false; - - el->setMark(1); - refineManager->refineElement(el->getMesh(), el); - } - - if (s1 != -1) - return fitElementToMeshCode2(refineManager, code, - el->getFirstChild(), s1, el->getChildType(elType)); - else - return fitElementToMeshCode2(refineManager, code, - el->getSecondChild(), s2, el->getChildType(elType)); - } - - bool fitElementToMeshCode2(RefinementManager *refineManager, MeshStructure &code, - Element *el, int ithSide, int elType) - { - if (code.isLeafElement()) - return false; - - bool value = false; - - if (el->isLeaf()) { - el->setMark(1); - refineManager->refineElement(el->getMesh(), el); - value = true; - } - - int s1 = el->getSideOfChild(0, ithSide, elType); - int s2 = el->getSideOfChild(1, ithSide, elType); - - if (s1 != -1) { - code.nextElement(); - value |= fitElementToMeshCode2(refineManager, code, el->getFirstChild(), - s1, el->getChildType(elType)); - } - - if (s2 != -1) { - code.nextElement(); - value |= fitElementToMeshCode2(refineManager, code, el->getSecondChild(), - s2, el->getChildType(elType)); - } - - return value; - } - } diff --git a/AMDiS/src/Element.h b/AMDiS/src/Element.h index 3955d6295883bf5c5deae44f512f45b2c7471b8c..4cfc027ee3e47e040eb1a65ffb9dca48ce4909e1 100644 --- a/AMDiS/src/Element.h +++ b/AMDiS/src/Element.h @@ -574,18 +574,6 @@ namespace AMDiS { friend class Mesh; }; - - bool fitElementToMeshCode(RefinementManager *refineManager, - MeshStructure &code, - Element *el, - int ithSide, - int elType); - - bool fitElementToMeshCode2(RefinementManager *refineManager, - MeshStructure &code, - Element *el, - int ithSide, - int elType); } #endif // AMDIS_ELEMENT_H diff --git a/AMDiS/src/InteriorBoundary.cc b/AMDiS/src/InteriorBoundary.cc index 2683b314486a8d1181ce72846d675294077a40cf..869f3705f87b3c4a1c870b5bdd2ee13ae86adfe0 100644 --- a/AMDiS/src/InteriorBoundary.cc +++ b/AMDiS/src/InteriorBoundary.cc @@ -76,12 +76,14 @@ namespace AMDiS { SerUtil::serialize(out, bound.rankObj.subObj); SerUtil::serialize(out, bound.rankObj.ithObj); SerUtil::serialize(out, bound.rankObj.reverseMode); + serializeExcludeList(out, bound.rankObj.excludedSubstructures); SerUtil::serialize(out, bound.neighObj.elIndex); SerUtil::serialize(out, bound.neighObj.elType); SerUtil::serialize(out, bound.neighObj.subObj); SerUtil::serialize(out, bound.neighObj.ithObj); SerUtil::serialize(out, bound.neighObj.reverseMode); + serializeExcludeList(out, bound.neighObj.excludedSubstructures); } } } @@ -107,16 +109,48 @@ namespace AMDiS { SerUtil::deserialize(in, bound.rankObj.subObj); SerUtil::deserialize(in, bound.rankObj.ithObj); SerUtil::deserialize(in, bound.rankObj.reverseMode); + deserializeExcludeList(in, bound.rankObj.excludedSubstructures); SerUtil::deserialize(in, bound.neighObj.elIndex); SerUtil::deserialize(in, bound.neighObj.elType); SerUtil::deserialize(in, bound.neighObj.subObj); SerUtil::deserialize(in, bound.neighObj.ithObj); SerUtil::deserialize(in, bound.neighObj.reverseMode); + deserializeExcludeList(in, bound.neighObj.excludedSubstructures); bound.rankObj.el = elIndexMap[bound.rankObj.elIndex]; bound.neighObj.el = NULL; } } } + + + void InteriorBoundary::serializeExcludeList(std::ostream &out, ExcludeList &list) + { + int size = list.size(); + SerUtil::serialize(out, size); + for (int i = 0; i < size; i++) { + SerUtil::serialize(out, list[i].first); + SerUtil::serialize(out, list[i].second); + } + } + + + void InteriorBoundary::deserializeExcludeList(std::istream &in, ExcludeList &list) + { + int size = 0; + SerUtil::deserialize(in, size); + list.resize(0); + list.reserve(size); + + for (int i = 0; i < size; i++) { + GeoIndex a; + int b; + + SerUtil::deserialize(in, a); + SerUtil::deserialize(in, b); + list.push_back(std::make_pair(a, b)); + } + } + } diff --git a/AMDiS/src/InteriorBoundary.h b/AMDiS/src/InteriorBoundary.h index 60078920c276f9bccdf98b09ae129dc30c13093b..ae85f77b869304f8f962973a258e37fe4b392a2d 100644 --- a/AMDiS/src/InteriorBoundary.h +++ b/AMDiS/src/InteriorBoundary.h @@ -31,12 +31,14 @@ namespace AMDiS { + typedef std::vector<std::pair<GeoIndex, int> > ExcludeList; + /// Defines the geometrical objects that forms the boundary; struct BoundaryObject { BoundaryObject() : reverseMode(false), - notIncludedSubStructures(0) + excludedSubstructures(0) {} BoundaryObject(Element *e, int eType, GeoIndex sObj, int iObj) @@ -46,7 +48,7 @@ namespace AMDiS { subObj(sObj), ithObj(iObj), reverseMode(false), - notIncludedSubStructures(0) + excludedSubstructures(0) {} void setReverseMode(BoundaryObject &otherBound, FiniteElemSpace *feSpace); @@ -83,7 +85,15 @@ namespace AMDiS { bool reverseMode; - std::vector<std::pair<GeoIndex, int> > notIncludedSubStructures; + /** \brief + * In many situations it may be necessary to exclude some parts of the element to + * be part of the boundary. In 3d, when a face is part of the boundary, an edge or + * an vertex may be exludeded. In 2d only vertices may be exluded to be part of + * an edge boundary. This list contains pairs of exludeded structures. The first + * component of every pair denotes if it is a vertex or an edge, and the second + * component denotes the local index of the structure. + */ + ExcludeList excludedSubstructures; }; /** \brief @@ -117,6 +127,11 @@ namespace AMDiS { /// Reads the state of an interior boundary from a file. void deserialize(std::istream &in, std::map<int, Element*> &elIndexMap); + protected: + void serializeExcludeList(std::ostream &out, ExcludeList &list); + + void deserializeExcludeList(std::istream &in, ExcludeList &list); + public: RankToBoundMap boundary; }; diff --git a/AMDiS/src/ParMetisPartitioner.cc b/AMDiS/src/ParMetisPartitioner.cc index 57b98cb0a056c34d92f643d41e618a5fd5cc0070..e9084ae419a9f71cb7540c431a24026634acde9f 100644 --- a/AMDiS/src/ParMetisPartitioner.cc +++ b/AMDiS/src/ParMetisPartitioner.cc @@ -287,14 +287,12 @@ namespace AMDiS { switch(mode) { case INITIAL: - // TODO: Removed weight because it does not work correctly for very large - // macro meshes. ParMETIS_V3_PartKway(parMetisMesh->getElementDist(), parMetisGraph.getXAdj(), parMetisGraph.getAdjncy(), + wgts, NULL, - NULL, - NULL, + &wgtflag, &numflag, &ncon, &nparts, diff --git a/AMDiS/src/ParallelDomainBase.cc b/AMDiS/src/ParallelDomainBase.cc index 23aaf48b3a958099dc7156a9817d18e3b335bd70..13bb00e41fc6e69d36ca1ee0c7b489eb0152f30d 100644 --- a/AMDiS/src/ParallelDomainBase.cc +++ b/AMDiS/src/ParallelDomainBase.cc @@ -1,4 +1,6 @@ #include <algorithm> +#include <iostream> +#include <fstream> #include "ParallelDomainBase.h" #include "ParMetisPartitioner.h" @@ -49,6 +51,8 @@ namespace AMDiS { mesh(fe->getMesh()), refineManager(refinementManager), initialPartitionMesh(true), + d_nnz(NULL), + o_nnz(NULL), nRankDofs(0), rstart(0), nComponents(1), @@ -364,38 +368,25 @@ namespace AMDiS { } - void ParallelDomainBase::fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec) + void ParallelDomainBase::createPetscNnzStructure(Matrix<DOFMatrix*> *mat) { - FUNCNAME("ParallelDomainBase::fillPetscMatrix()"); - - clock_t first = clock(); - - // === Create PETSc vector (rhs, solution and a temporary vector). === + FUNCNAME("ParallelDomainBase::createPetscNnzStructure()"); - VecCreate(PETSC_COMM_WORLD, &petscRhsVec); - VecSetSizes(petscRhsVec, nRankRows, nOverallRows); - VecSetType(petscRhsVec, VECMPI); - - VecCreate(PETSC_COMM_WORLD, &petscSolVec); - VecSetSizes(petscSolVec, nRankRows, nOverallRows); - VecSetType(petscSolVec, VECMPI); + TEST_EXIT_DBG(!d_nnz)("There is something wrong!\n"); + TEST_EXIT_DBG(!o_nnz)("There is something wrong!\n"); - VecCreate(PETSC_COMM_WORLD, &petscTmpVec); - VecSetSizes(petscTmpVec, nRankRows, nOverallRows); - VecSetType(petscTmpVec, VECMPI); + d_nnz = new int[nRankRows]; + o_nnz = new int[nRankRows]; + for (int i = 0; i < nRankRows; i++) { + d_nnz[i] = 0; + o_nnz[i] = 0; + } using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end; namespace traits = mtl::traits; typedef DOFMatrix::base_matrix_type Matrix; typedef std::vector<std::pair<int, int> > MatrixNnzEntry; - int d_nnz[nRankRows]; - int o_nnz[nRankRows]; - for (int i = 0; i < nRankRows; i++) { - d_nnz[i] = 0; - o_nnz[i] = 0; - } - // Stores to each rank a list of nnz entries (i.e. pairs of row and column index) // that this rank will send to. This nnz entries will be assembled on this rank, // but because the row DOFs are not DOFs of this rank they will be send to the @@ -531,12 +522,39 @@ namespace AMDiS { } } } + } + + + void ParallelDomainBase::fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec) + { + FUNCNAME("ParallelDomainBase::fillPetscMatrix()"); + + clock_t first = clock(); + + // === Create PETSc vector (rhs, solution and a temporary vector). === + + VecCreate(PETSC_COMM_WORLD, &petscRhsVec); + VecSetSizes(petscRhsVec, nRankRows, nOverallRows); + VecSetType(petscRhsVec, VECMPI); + + VecCreate(PETSC_COMM_WORLD, &petscSolVec); + VecSetSizes(petscSolVec, nRankRows, nOverallRows); + VecSetType(petscSolVec, VECMPI); + + VecCreate(PETSC_COMM_WORLD, &petscTmpVec); + VecSetSizes(petscTmpVec, nRankRows, nOverallRows); + VecSetType(petscTmpVec, VECMPI); + + if (!d_nnz) + createPetscNnzStructure(mat); // === Create PETSc matrix with the computed nnz data structure. === MatCreateMPIAIJ(PETSC_COMM_WORLD, nRankRows, nRankRows, nOverallRows, nOverallRows, 0, d_nnz, 0, o_nnz, &petscMatrix); + INFO(info, 8)("Fill petsc matrix 1 needed %.5f seconds\n", TIME_USED(first, clock())); + #if (DEBUG != 0) int a, b; MatGetOwnershipRange(petscMatrix, &a, &b); @@ -551,6 +569,8 @@ namespace AMDiS { if ((*mat)[i][j]) setDofMatrix((*mat)[i][j], nComponents, i, j); + INFO(info, 8)("Fill petsc matrix 2 needed %.5f seconds\n", TIME_USED(first, clock())); + MatAssemblyBegin(petscMatrix, MAT_FINAL_ASSEMBLY); MatAssemblyEnd(petscMatrix, MAT_FINAL_ASSEMBLY); @@ -727,10 +747,20 @@ namespace AMDiS { do { // To check the interior boundaries, the ownership of the boundaries is not // important. Therefore, we add all boundaries to one boundary container. - RankToBoundMap allBound = myIntBoundary.boundary; + RankToBoundMap allBound; + for (RankToBoundMap::iterator it = myIntBoundary.boundary.begin(); + it != myIntBoundary.boundary.end(); ++it) + for (std::vector<AtomicBoundary>::iterator bit = it->second.begin(); + bit != it->second.end(); ++bit) + if (bit->rankObj.subObj == FACE) + allBound[it->first].push_back(*bit); + for (RankToBoundMap::iterator it = otherIntBoundary.boundary.begin(); it != otherIntBoundary.boundary.end(); ++it) - allBound[it->first] = it->second; + for (std::vector<AtomicBoundary>::iterator bit = it->second.begin(); + bit != it->second.end(); ++bit) + if (bit->rankObj.subObj == FACE) + allBound[it->first].push_back(*bit); // === Check the boundaries and adapt mesh if necessary. === @@ -741,6 +771,7 @@ namespace AMDiS { int sendValue = static_cast<int>(!meshChanged); recvAllValues = 0; mpiComm.Allreduce(&sendValue, &recvAllValues, 1, MPI_INT, MPI_SUM); + MSG("LOOP\n"); } while (recvAllValues != 0); @@ -754,6 +785,19 @@ namespace AMDiS { // === Because the mesh has been changed, update the DOF numbering and mappings. === updateLocalGlobalNumbering(); + + // === If there is a non zero pattern computed for Petsc matrix, delete it. So === + // === it will be recomputed after next assembling. === + + if (d_nnz) { + delete [] d_nnz; + d_nnz = NULL; + } + + if (o_nnz) { + delete [] o_nnz; + o_nnz = NULL; + } } @@ -761,6 +805,8 @@ namespace AMDiS { { FUNCNAME("ParallelDomainBase::checkAndAdaptBoundary()"); + MSG("CHECK_AND_ADAPT 1!\n"); + // === Create mesh structure codes for all ranks boundary elements. === std::map<int, MeshCodeVec> sendCodes; @@ -774,14 +820,21 @@ namespace AMDiS { } } + MSG("CHECK_AND_ADAPT 2!\n"); + StdMpi<MeshCodeVec> stdMpi(mpiComm, true); stdMpi.send(sendCodes); stdMpi.recv(allBound); stdMpi.startCommunication<unsigned long int>(MPI_UNSIGNED_LONG); + MSG("CHECK_AND_ADAPT 3!\n"); + + clock_t first = clock(); + // === Compare received mesh structure codes. === bool meshFitTogether = true; + int superCounter = 0; for (RankToBoundMap::iterator it = allBound.begin(); it != allBound.end(); ++it) { @@ -790,18 +843,27 @@ namespace AMDiS { for (std::vector<AtomicBoundary>::iterator boundIt = it->second.begin(); boundIt != it->second.end(); ++boundIt) { - + MeshStructure elCode; elCode.init(boundIt->rankObj); if (elCode.getCode() != recvCodes[i].getCode()) { TEST_EXIT_DBG(refineManager)("Refinement manager is not set correctly!\n"); - - bool b = fitElementToMeshCode(refineManager, - recvCodes[i], + superCounter++; + clock_t fff = clock(); + + int refCounter = 0; + bool b = fitElementToMeshCode(recvCodes[i], boundIt->rankObj.el, boundIt->rankObj.ithObj, - boundIt->rankObj.elType); + boundIt->rankObj.elType, refCounter); + + MSG("SIZE OF ELINFO3d = %d\n", sizeof(ElInfo3d)); + MSG("Code length %d with %d refs needed %.5f seconds\n", + recvCodes[i].getNumElements(), + refCounter, + TIME_USED(fff, clock())); + if (b) meshFitTogether = false; } @@ -810,9 +872,84 @@ namespace AMDiS { } } + MSG("time for %d needed %.5f seconds\n", superCounter, TIME_USED(first, clock())); + MSG("CHECK_AND_ADAPT 4!\n"); + return meshFitTogether; } - + + + bool ParallelDomainBase::fitElementToMeshCode(MeshStructure &code, + Element *el, + int ithSide, + int elType, + int &refCounter) + { + FUNCNAME("fitElementToMeshCode()"); + + if (code.empty()) + return false; + + int s1 = el->getSideOfChild(0, ithSide, elType); + int s2 = el->getSideOfChild(1, ithSide, elType); + + TEST_EXIT_DBG(s1 != -1 || s2 != -1)("This should not happen!\n"); + + if (s1 != -1 && s2 != -1) + return fitElementToMeshCode2(code, el, ithSide, elType, refCounter); + + if (el->isLeaf()) { + if (code.getNumElements() == 1 && code.isLeafElement()) + return false; + + el->setMark(1); + refineManager->refineElement(el->getMesh(), el); + refCounter++; + } + + if (s1 != -1) + return fitElementToMeshCode2(code, + el->getFirstChild(), s1, el->getChildType(elType), refCounter); + else + return fitElementToMeshCode2(code, + el->getSecondChild(), s2, el->getChildType(elType), refCounter); + } + + bool ParallelDomainBase::fitElementToMeshCode2(MeshStructure &code, + Element *el, + int ithSide, + int elType, int &refCounter) + { + if (code.isLeafElement()) + return false; + + bool value = false; + + if (el->isLeaf()) { + el->setMark(1); + refineManager->refineElement(el->getMesh(), el); + value = true; + refCounter++; + } + + int s1 = el->getSideOfChild(0, ithSide, elType); + int s2 = el->getSideOfChild(1, ithSide, elType); + + if (s1 != -1) { + code.nextElement(); + value |= fitElementToMeshCode2(code, el->getFirstChild(), + s1, el->getChildType(elType), refCounter); + } + + if (s2 != -1) { + code.nextElement(); + value |= fitElementToMeshCode2(code, el->getSecondChild(), + s2, el->getChildType(elType), refCounter); + } + + return value; + } + void ParallelDomainBase::serialize(std::ostream &out, DofContainer &data) { @@ -872,32 +1009,55 @@ namespace AMDiS { double ParallelDomainBase::setElemWeights(AdaptInfo *adaptInfo) { - double localWeightSum = 0.0; - int elNum = -1; + FUNCNAME("ParallelDomainBase::setElemWeights()"); + double localWeightSum = 0.0; elemWeights.clear(); + + std::string filename = ""; + GET_PARAMETER(0, mesh->getName() + "->macro weights", &filename); + if (filename != "") { + MSG("Read macro weights from %s\n", filename.c_str()); + + std::ifstream infile; + infile.open(filename.c_str(), std::ifstream::in); + while (!infile.eof()) { + int elNum, elWeight; + infile >> elNum; + if (infile.eof()) + break; + infile >> elWeight; - 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)); + elemWeights[elNum] = elWeight; + localWeightSum += elWeight; + } - if (partitionData && partitionData->getPartitionStatus() == IN) { - if (partitionData->getLevel() == 0) - elNum = element->getIndex(); + infile.close(); + } else { + + 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)); - TEST_EXIT_DBG(elNum != -1)("invalid element number\n"); - if (element->isLeaf()) { - elemWeights[elNum] += 1.0; - localWeightSum += 1.0; + if (partitionData && partitionData->getPartitionStatus() == IN) { + int elNum = -1; + if (partitionData->getLevel() == 0) + elNum = element->getIndex(); + + TEST_EXIT_DBG(elNum != -1)("invalid element number\n"); + if (element->isLeaf()) { + elemWeights[elNum] += 1.0; + localWeightSum += 1.0; + } } + + elInfo = stack.traverseNext(elInfo); } - - elInfo = stack.traverseNext(elInfo); } return localWeightSum; @@ -1229,7 +1389,7 @@ namespace AMDiS { // Otherwise, it is part of the interior boundary and we add it to the set // rankBoundaryEdges. if (edgeOwner[edge] > mpiRank) - boundIt->rankObj.notIncludedSubStructures.push_back(std::pair<GeoIndex, int>(EDGE, edgeNo)); + boundIt->rankObj.excludedSubstructures.push_back(std::make_pair(EDGE, edgeNo)); else rankBoundaryEdges.insert(edge); } @@ -1240,7 +1400,7 @@ namespace AMDiS { DegreeOfFreedom dof = localIndices[dofNo]; if (dofOwner[dof] > mpiRank) - boundIt->rankObj.notIncludedSubStructures.push_back(std::pair<GeoIndex, int>(VERTEX, dofNo)); + boundIt->rankObj.excludedSubstructures.push_back(std::make_pair(VERTEX, dofNo)); else rankBoundaryDofs.insert(dof); } @@ -1262,7 +1422,7 @@ namespace AMDiS { GlobalEdge edge = std::make_pair(min(dof0, dof1), max(dof0, dof1)); if (edgeOwner[edge] > rankIt->first) - boundIt->rankObj.notIncludedSubStructures.push_back(std::pair<GeoIndex, int>(EDGE, edgeNo)); + boundIt->rankObj.excludedSubstructures.push_back(std::make_pair(EDGE, edgeNo)); else rankBoundaryEdges.insert(edge); @@ -1273,7 +1433,7 @@ namespace AMDiS { DegreeOfFreedom dof = localIndices[dofNo]; if (dofOwner[dof] > rankIt->first) - boundIt->rankObj.notIncludedSubStructures.push_back(std::pair<GeoIndex, int>(VERTEX, dofNo)); + boundIt->rankObj.excludedSubstructures.push_back(std::make_pair(VERTEX, dofNo)); else rankBoundaryDofs.insert(dof); } @@ -1816,8 +1976,7 @@ namespace AMDiS { // === Send new DOF indices. === -#if 0 - StdMpi<std::vector<DegreeOfFreedom> > stdMpi(mpiComm); + StdMpi<std::vector<DegreeOfFreedom> > stdMpi(mpiComm, false); for (RankToDofContainer::iterator sendIt = sendDofs.begin(); sendIt != sendDofs.end(); ++sendIt, i++) { stdMpi.getSendData(sendIt->first).resize(0); @@ -1826,56 +1985,18 @@ namespace AMDiS { dofIt != sendIt->second.end(); ++dofIt) stdMpi.getSendData(sendIt->first).push_back(rankDofsNewGlobalIndex[*dofIt]); } -#endif - - std::vector<int*> sendBuffers(sendDofs.size()); - std::vector<int*> recvBuffers(recvDofs.size()); - - MPI::Request request[sendDofs.size() + recvDofs.size()]; - int requestCounter = 0; - - i = 0; - for (RankToDofContainer::iterator sendIt = sendDofs.begin(); - sendIt != sendDofs.end(); ++sendIt, i++) { - int nSendDofs = sendIt->second.size(); - sendBuffers[i] = new int[nSendDofs]; - int c = 0; - for (DofContainer::iterator dofIt = sendIt->second.begin(); - dofIt != sendIt->second.end(); ++dofIt) - sendBuffers[i][c++] = rankDofsNewGlobalIndex[*dofIt]; - - request[requestCounter++] = - mpiComm.Isend(sendBuffers[i], nSendDofs, MPI_INT, sendIt->first, 0); - } - - i = 0; - for (RankToDofContainer::iterator recvIt = recvDofs.begin(); - recvIt != recvDofs.end(); ++recvIt, i++) { - int nRecvDofs = recvIt->second.size(); - recvBuffers[i] = new int[nRecvDofs]; - - request[requestCounter++] = - mpiComm.Irecv(recvBuffers[i], nRecvDofs, MPI_INT, recvIt->first, 0); - } - - MPI::Request::Waitall(requestCounter, request); - - for (int j = 0; j < static_cast<int>(sendBuffers.size()); j++) - delete [] sendBuffers[j]; + stdMpi.updateSendDataSize(); + stdMpi.recv(recvDofs); + stdMpi.startCommunication<int>(MPI_INT); - i = 0; for (RankToDofContainer::iterator recvIt = recvDofs.begin(); recvIt != recvDofs.end(); ++recvIt) { int j = 0; for (DofContainer::iterator dofIt = recvIt->second.begin(); dofIt != recvIt->second.end(); ++dofIt) { - - rankDofsNewGlobalIndex[*dofIt] = recvBuffers[i][j]; + rankDofsNewGlobalIndex[*dofIt] = stdMpi.getRecvData(recvIt->first)[j++]; isRankDof[rankDofsNewLocalIndex[*dofIt]] = false; - j++; } - - delete [] recvBuffers[i++]; } // === Create now the local to global index and local to dof index mappings. === @@ -2017,23 +2138,18 @@ namespace AMDiS { // Clear all periodic dof mappings calculated before. We do it from scratch. periodicDof.clear(); - MPI::Request request[min(static_cast<int>(periodicBoundary.boundary.size() * 2), 4)]; - int requestCounter = 0; - std::vector<int*> sendBuffers, recvBuffers; + StdMpi<std::vector<int> > stdMpi(mpiComm, false); // === Each rank traverse its periodic boundaries and sends the dof indices === // === to the rank "on the other side" of the periodic boundary. === for (RankToBoundMap::iterator it = periodicBoundary.boundary.begin(); it != periodicBoundary.boundary.end(); ++it) { - TEST_EXIT_DBG(it->first != mpiRank) ("Periodic interior boundary within the rank itself is not possible!\n"); - DofContainer dofs; - // Create dof indices on the boundary. - + DofContainer dofs; for (std::vector<AtomicBoundary>::iterator boundIt = it->second.begin(); boundIt != it->second.end(); ++boundIt) { boundIt->rankObj.el->getVertexDofs(feSpace, boundIt->rankObj, dofs); @@ -2041,27 +2157,16 @@ namespace AMDiS { } // Send the global indices to the rank on the other side. - - int *sendbuf = new int[dofs.size()]; + stdMpi.getSendData(it->first).reserve(dofs.size()); for (int i = 0; i < static_cast<int>(dofs.size()); i++) - sendbuf[i] = mapLocalGlobalDofs[*(dofs[i])]; - - request[requestCounter++] = - mpiComm.Isend(sendbuf, dofs.size(), MPI_INT, it->first, 0); - - sendBuffers.push_back(sendbuf); + stdMpi.getSendData(it->first).push_back(mapLocalGlobalDofs[*(dofs[i])]); // Receive from this rank the same number of dofs. - - int *recvbuf = new int[dofs.size()]; - request[requestCounter++] = - mpiComm.Irecv(recvbuf, dofs.size(), MPI_INT, it->first, 0); - - recvBuffers.push_back(recvbuf); + stdMpi.recv(it->first, dofs.size()); } - - MPI::Request::Waitall(requestCounter, request); + stdMpi.updateSendDataSize(); + stdMpi.startCommunication<int>(MPI_INT); // === The rank has received the dofs from the rank on the other side of === // === the boundary. Now it can use them to create the mapping between === @@ -2070,8 +2175,6 @@ namespace AMDiS { std::map<DegreeOfFreedom, std::set<int> > dofFromRank; - - int i = 0; for (RankToBoundMap::iterator it = periodicBoundary.boundary.begin(); it != periodicBoundary.boundary.end(); ++it) { DofContainer dofs; @@ -2090,23 +2193,19 @@ namespace AMDiS { // Added the received dofs to the mapping. for (int j = 0; j < static_cast<int>(dofs.size()); j++) { int globalDofIndex = mapLocalGlobalDofs[*(dofs[j])]; - periodicDof[globalDofIndex].insert(recvBuffers[i][j]); + periodicDof[globalDofIndex].insert(stdMpi.getRecvData(it->first)[j]); dofFromRank[globalDofIndex].insert(it->first); } - - delete [] sendBuffers[i]; - delete [] recvBuffers[i]; - i++; } - sendBuffers.clear(); - recvBuffers.clear(); - if (dofFromRank.size() > 0) TEST_EXIT_DBG(mesh->getDim() == 2) ("Periodic boundary corner problem must be generalized to 3d!\n"); - requestCounter = 0; + MPI::Request request[min(static_cast<int>(periodicBoundary.boundary.size() * 2), 4)]; + int requestCounter = 0; + std::vector<int*> sendBuffers, recvBuffers; + for (std::map<DegreeOfFreedom, std::set<int> >::iterator it = dofFromRank.begin(); it != dofFromRank.end(); ++it) { if (it->second.size() == 2) { @@ -2138,7 +2237,7 @@ namespace AMDiS { MPI::Request::Waitall(requestCounter, request); - i = 0; + int i = 0; for (std::map<DegreeOfFreedom, std::set<int> >::iterator it = dofFromRank.begin(); it != dofFromRank.end(); ++it) { if (it->second.size() == 2) { diff --git a/AMDiS/src/ParallelDomainBase.h b/AMDiS/src/ParallelDomainBase.h index d04c90a1bf78b1d65c68cf6add10246cbe8badc0..326843016a42fbb1c35f672ba4385d065b72553c 100644 --- a/AMDiS/src/ParallelDomainBase.h +++ b/AMDiS/src/ParallelDomainBase.h @@ -101,6 +101,15 @@ namespace AMDiS { virtual void exitParallelization(AdaptInfo *adaptInfo); + /** \brief + * This function checks if the mesh has changed on at least on rank. In this case, + * the interior boundaries are adapted on all ranks such that they fit together on + * all ranks. Furthermore the function \ref updateLocalGlobalNumbering() is called + * to update the dof numberings and mappings on all rank due to the new mesh + * structure. + */ + void checkMeshChange(); + void updateDofAdmins(); /** \brief @@ -184,7 +193,6 @@ namespace AMDiS { { return NULL; } - // Writes all data of this object to an output stream. virtual void serialize(std::ostream &out); @@ -265,6 +273,9 @@ namespace AMDiS { DofToRank& boundaryDofs, DofToBool& vertexDof); + /// Creates a new non zero pattern structure for the Petsc matrix. + void createPetscNnzStructure(Matrix<DOFMatrix*> *mat); + /** \brief * Create a PETSc matrix and PETSc vectors. The given DOF matrices are used to * create the nnz structure of the PETSc matrix and the values are transfered to it. @@ -283,15 +294,6 @@ namespace AMDiS { void setDofVector(Vec& petscVec, DOFVector<double>* vec, int disMult = 1, int dispAdd = 0); - /** \brief - * This function checks if the mesh has changed on at least on rank. In this case, - * the interior boundaries are adapted on all ranks such that they fit together on - * all ranks. Furthermore the function \ref updateLocalGlobalNumbering() is called - * to update the dof numberings and mappings on all rank due to the new mesh - * structure. - */ - void checkMeshChange(); - /** \brief * Checks for all given interior boundaries if the elements fit together on both * sides of the boundaries. If this is not the case, the mesh is adapted. Because @@ -376,6 +378,18 @@ namespace AMDiS { */ void synchVector(SystemVector &vec); + bool fitElementToMeshCode(MeshStructure &code, + Element *el, + int ithSide, + int elType, + int &refCounter); + + bool fitElementToMeshCode2(MeshStructure &code, + Element *el, + int ithSide, + int elType, + int &refCounter); + /// Writes a vector of dof pointers to an output stream. void serialize(std::ostream &out, DofContainer &data); @@ -536,6 +550,9 @@ namespace AMDiS { * temporary vector for calculating the final residuum. */ Vec petscRhsVec, petscSolVec, petscTmpVec; + + /// Arrays definig the non zero pattern of Petsc's matrix. + int *d_nnz, *o_nnz; /// Number of DOFs in the rank mesh. int nRankDofs; diff --git a/AMDiS/src/StdMpi.h b/AMDiS/src/StdMpi.h index 41d72e13e22af127bf8be311eb1de31c5f206b2f..56bd928a040678dd5431e60ac3d71f921dfdc4d7 100644 --- a/AMDiS/src/StdMpi.h +++ b/AMDiS/src/StdMpi.h @@ -297,6 +297,13 @@ namespace AMDiS { return sendData[rank]; } + void updateSendDataSize() + { + for (typename std::map<int, SendT>::iterator it = sendData.begin(); + it != sendData.end(); ++it) + sendDataSize[it->first] = intSizeOf(it->second); + } + void recv(int fromRank, int size = -1) { FUNCNAME("StdMpi::recv()"); diff --git a/AMDiS/src/Tetrahedron.cc b/AMDiS/src/Tetrahedron.cc index 8a34ec25598b27e1184d3b64f6da7c8f60759934..8899c1f2fe343318ade1297d1f959159f8e36932 100644 --- a/AMDiS/src/Tetrahedron.cc +++ b/AMDiS/src/Tetrahedron.cc @@ -215,7 +215,7 @@ namespace AMDiS { { if (parentVertices) { - ERROR_EXIT("Einbau notIncludedSubStructures!\n"); + ERROR_EXIT("Einbau excludedSubstructures!\n"); switch (bound.ithObj) { case 0: @@ -264,8 +264,8 @@ namespace AMDiS { nextBound1.reverseMode = false; bool addDof = true; - for (std::vector<std::pair<GeoIndex, int> >::iterator it = bound.notIncludedSubStructures.begin(); - it != bound.notIncludedSubStructures.end(); ++it) + for (ExcludeList::iterator it = bound.excludedSubstructures.begin(); + it != bound.excludedSubstructures.end(); ++it) if (it->first == EDGE && it->second == 0) addDof = false; @@ -300,7 +300,7 @@ namespace AMDiS { FUNCNAME("Tetrahedron::getVertexDofsAtEdge()"); if (parentVertices) { - ERROR_EXIT("Einbau notIncludedSubStructures!\n"); + ERROR_EXIT("Einbau excludedSubstructures!\n"); } if (!child[0]) @@ -330,8 +330,8 @@ namespace AMDiS { switch (bound.subObj) { case FACE: - for (std::vector<std::pair<GeoIndex, int> >::iterator it = bound.notIncludedSubStructures.begin(); - it != bound.notIncludedSubStructures.end(); ++it) { + for (ExcludeList::iterator it = bound.excludedSubstructures.begin(); + it != bound.excludedSubstructures.end(); ++it) { if (it->first == EDGE) it->second = edgeOfChild[bound.elType][ithChild][it->second]; }