From ab09fcdad6ff564066a4a6e14a58fba59fae0dcc Mon Sep 17 00:00:00 2001 From: Thomas Witkowski <thomas.witkowski@gmx.de> Date: Thu, 24 Jun 2010 16:16:32 +0000 Subject: [PATCH] Fixed serialization problem for parallel computations, work on periodic bc in parallel code. --- AMDiS/configure | 2 +- AMDiS/configure.ac | 2 +- AMDiS/libtool | 8 +-- AMDiS/src/MeshStructure.cc | 2 + AMDiS/src/Parameters.cc | 10 ++- AMDiS/src/Parameters.h | 13 ++-- AMDiS/src/ProblemVec.cc | 6 +- AMDiS/src/ProblemVec.h | 10 +++ AMDiS/src/Serializer.h | 19 ++++- AMDiS/src/parallel/InteriorBoundary.cc | 6 ++ AMDiS/src/parallel/ParallelDomainBase.cc | 91 ++++++++++++++++++------ AMDiS/src/parallel/ParallelDomainBase.h | 9 +-- 12 files changed, 130 insertions(+), 48 deletions(-) diff --git a/AMDiS/configure b/AMDiS/configure index b4b86c5b..c6071d46 100755 --- a/AMDiS/configure +++ b/AMDiS/configure @@ -2074,7 +2074,7 @@ fi; MPI_DIR=$mpidir if test $mpidir != no ; then - CXX=$mpidir/bin/mpiCC + CXX=$mpidir/bin/mpicxx CC=$mpidir/bin/mpicc diff --git a/AMDiS/configure.ac b/AMDiS/configure.ac index 8bc69e3d..7f0e38de 100644 --- a/AMDiS/configure.ac +++ b/AMDiS/configure.ac @@ -50,7 +50,7 @@ fi AC_ARG_WITH(mpi, [ --with-mpi=MPI_DIR], mpidir=$withval, mpidir=no) AC_SUBST(MPI_DIR, $mpidir) if test $mpidir != no ; then - AC_SUBST(CXX, $mpidir/bin/mpiCC) + AC_SUBST(CXX, $mpidir/bin/mpicxx) AC_SUBST(CC, $mpidir/bin/mpicc) fi diff --git a/AMDiS/libtool b/AMDiS/libtool index ae88f17c..03d745bb 100755 --- a/AMDiS/libtool +++ b/AMDiS/libtool @@ -44,7 +44,7 @@ available_tags=" CXX F77" # ### BEGIN LIBTOOL CONFIG -# Libtool was configured on host p2q084: +# Libtool was configured on host p1q020: # Shell to use when invoking shell scripts. SHELL="/bin/sh" @@ -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 p2q084: +# Libtool was configured on host p1q020: # Shell to use when invoking shell scripts. SHELL="/bin/sh" @@ -6804,7 +6804,7 @@ LTCC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicc" LTCFLAGS="-g -O2" # A language-specific compiler. -CC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpiCC" +CC="/licsoft/libraries/openmpi/1.2.6/64bit/bin/mpicxx" # Is the compiler the GNU C compiler? with_gcc=yes @@ -7065,7 +7065,7 @@ include_expsyms="" # ### BEGIN LIBTOOL TAG CONFIG: F77 -# Libtool was configured on host p2q084: +# Libtool was configured on host p1q020: # Shell to use when invoking shell scripts. SHELL="/bin/sh" diff --git a/AMDiS/src/MeshStructure.cc b/AMDiS/src/MeshStructure.cc index 94637989..05da7b3c 100644 --- a/AMDiS/src/MeshStructure.cc +++ b/AMDiS/src/MeshStructure.cc @@ -63,6 +63,8 @@ namespace AMDiS { Element *el = bound.el; + TEST_EXIT_DBG(el)("No element!\n"); + clear(); int s1 = el->getSubObjOfChild(0, bound.subObj, bound.ithObj, bound.elType); diff --git a/AMDiS/src/Parameters.cc b/AMDiS/src/Parameters.cc index be044b70..92a1149e 100644 --- a/AMDiS/src/Parameters.cc +++ b/AMDiS/src/Parameters.cc @@ -33,7 +33,7 @@ namespace AMDiS { if (Parameters::singlett->paramInfo) { if (Parameters::singlett->paramInfo > 1) - info = max(info, Parameters::singlett->paramInfo-1); + info = max(info, Parameters::singlett->paramInfo - 1); } else { info = 0; } @@ -47,7 +47,8 @@ namespace AMDiS { } } - i = std::find(Parameters::singlett->allParam.begin(),Parameters::singlett->allParam.end(),tParam); + i = std::find(Parameters::singlett->allParam.begin(), + Parameters::singlett->allParam.end(), tParam); if (i == Parameters::singlett->allParam.end()) { if (funcName != funcName2) { @@ -186,6 +187,7 @@ namespace AMDiS { return count; } + int Parameters::getGlobalParameter(int flag, const std::string& key, std::string* param) { @@ -197,6 +199,7 @@ namespace AMDiS { return result; } + void Parameters::read(const std::string& aFilename, const std::string& maxKey) { @@ -238,6 +241,7 @@ namespace AMDiS { singlett->inputFile.close(); } + const std::string& Parameters::getActFile(const std::string& aFilename) { FUNCNAME("Parameters::getActFile()"); @@ -255,6 +259,7 @@ namespace AMDiS { } } + void Parameters::swap(int i, int j) { param tmp(allParam[i]); @@ -262,6 +267,7 @@ namespace AMDiS { allParam[j] = tmp; } + void Parameters::qsort(int left, int right) { if (left >= right) diff --git a/AMDiS/src/Parameters.h b/AMDiS/src/Parameters.h index 4eb0ed27..e331285b 100644 --- a/AMDiS/src/Parameters.h +++ b/AMDiS/src/Parameters.h @@ -171,9 +171,9 @@ namespace AMDiS { * specified in a parameter file. * \see GET_PARAMETER */ - static int getGlobalParameter(int flag, - const std::string& key, - const char *format, + static int getGlobalParameter(int flag, + const std::string& key, + const char *format, ...); /// Like getGlobalParameter(flag, key, "%s", param->c_str()). @@ -245,7 +245,7 @@ namespace AMDiS { const std::string& nparameters, const std::string& nfilename, const std::string& nfuncName, - int line) + int line) : key(nkey), parameters(nparameters), filename(nfilename), @@ -327,15 +327,14 @@ namespace AMDiS { private: std::string cppFlags; std::ifstream inputFile; - std::list< std::string> filenames; + std::list<std::string> filenames; size_t maxFiles; std::string filename; int paramInfo; int msgInfo; int msgWait; std::vector<param> allParam; - - }; + }; /** \brief diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc index a8f12021..da190afe 100644 --- a/AMDiS/src/ProblemVec.cc +++ b/AMDiS/src/ProblemVec.cc @@ -184,6 +184,8 @@ namespace AMDiS { MSG("Deserialization from file: %s\n", serializationFilename.c_str()); #endif + + deserialized = true; } else { int globalRefinements = 0; @@ -476,12 +478,8 @@ namespace AMDiS { GET_PARAMETER(0, name + "->output->write serialization", "%d", &writeSerialization); - // Serialization is not allowed to be done by the problem, if its part of a parallel - // problem definition. Than, the parallel problem object must be serialized. -#ifndef HAVE_PARALLEL_DOMAIN_AMDIS if (writeSerialization) fileWriters.push_back(new Serializer<ProblemVec>(this)); -#endif } diff --git a/AMDiS/src/ProblemVec.h b/AMDiS/src/ProblemVec.h index 567e7d4d..26b22f50 100644 --- a/AMDiS/src/ProblemVec.h +++ b/AMDiS/src/ProblemVec.h @@ -63,6 +63,7 @@ namespace AMDiS { systemMatrix(NULL), useGetBound(true), info(10), + deserialized(false), computeExactError(false), boundaryConditionSet(false), writeAsmInfo(false) @@ -411,6 +412,12 @@ namespace AMDiS { return info; } + /// Returns \ref deserialized; + bool isDeserialized() + { + return deserialized; + } + /** \} */ /** \name setting methods @@ -601,6 +608,9 @@ namespace AMDiS { /// Info level. int info; + /// If true, the stationary problem was deserialized from some serialization file. + bool deserialized; + /** \brief * This vectors stores pointers to functions defining the exact solution of * the problem. This may be used to compute the real error of the computed diff --git a/AMDiS/src/Serializer.h b/AMDiS/src/Serializer.h index 0f594d01..d4cc93a7 100644 --- a/AMDiS/src/Serializer.h +++ b/AMDiS/src/Serializer.h @@ -46,13 +46,30 @@ namespace AMDiS { GET_PARAMETER(0, problem->getName() + "->output->serialization filename", &name); GET_PARAMETER(0, problem->getName() + "->output->write every i-th timestep", "%d", &tsModulo); - TEST_EXIT(name != "")("no filename\n"); + TEST_EXIT(name != "")("No filename!\n"); #if HAVE_PARALLEL_DOMAIN_AMDIS name += ".p" + boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank()); #endif } + + Serializer(ProblemType *prob, std::string filename, int writeEveryIth) + : name(filename), + problem(prob), + tsModulo(writeEveryIth), + timestepNumber(-1) + { + FUNCNAME("Serializer::Serializer()"); + + TEST_EXIT(name != "")("No filename!\n"); + +#if HAVE_PARALLEL_DOMAIN_AMDIS + name += ".p" + boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank()); +#endif + } + + virtual ~Serializer() {} virtual void writeFiles(AdaptInfo *adaptInfo, diff --git a/AMDiS/src/parallel/InteriorBoundary.cc b/AMDiS/src/parallel/InteriorBoundary.cc index 878eb36e..068b4a25 100644 --- a/AMDiS/src/parallel/InteriorBoundary.cc +++ b/AMDiS/src/parallel/InteriorBoundary.cc @@ -120,6 +120,8 @@ namespace AMDiS { void InteriorBoundary::deserialize(std::istream &in, std::map<int, Element*> &elIndexMap) { + FUNCNAME("InteriorBoundary::deserialize()"); + int mSize = 0; SerUtil::deserialize(in, mSize); for (int i = 0; i < mSize; i++) { @@ -146,6 +148,10 @@ namespace AMDiS { SerUtil::deserialize(in, bound.neighObj.reverseMode); deserializeExcludeList(in, bound.neighObj.excludedSubstructures); + TEST_EXIT_DBG(elIndexMap.count(bound.rankObj.elIndex) == 1) + ("Cannot find element with index %d for deserialization!\n", + bound.rankObj.elIndex); + bound.rankObj.el = elIndexMap[bound.rankObj.elIndex]; bound.neighObj.el = NULL; } diff --git a/AMDiS/src/parallel/ParallelDomainBase.cc b/AMDiS/src/parallel/ParallelDomainBase.cc index 91719195..9ba19d5d 100644 --- a/AMDiS/src/parallel/ParallelDomainBase.cc +++ b/AMDiS/src/parallel/ParallelDomainBase.cc @@ -2,6 +2,8 @@ #include <iostream> #include <fstream> #include <boost/lexical_cast.hpp> +#include <boost/filesystem.hpp> + #include "parallel/ParallelDomainBase.h" #include "parallel/ParallelDomainDbg.h" #include "parallel/StdMpi.h" @@ -29,6 +31,7 @@ namespace AMDiS { using boost::lexical_cast; + using namespace boost::filesystem; inline bool cmpDofsByValue(const DegreeOfFreedom* dof1, const DegreeOfFreedom* dof2) { @@ -49,6 +52,7 @@ namespace AMDiS { nOverallDofs(0), rstart(0), deserialized(false), + writeSerializationFile(false), lastMeshChangeIndex(0), macroElementStructureConsisten(false) { @@ -253,23 +257,49 @@ namespace AMDiS { // Create parallel serialization file writer, if needed. int writeSerialization = 0; - GET_PARAMETER(0, probVec->getName() + "->output->write serialization", "%d", &writeSerialization); - if (writeSerialization) - probVec->getFileWriterList().push_back(new Serializer<MeshDistributor>(this)); + GET_PARAMETER(0, probVec->getName() + "->output->write serialization", "%d", + &writeSerialization); + if (writeSerialization && !writeSerializationFile) { + std::string f = ""; + GET_PARAMETER(0, probVec->getName() + "->output->serialization filename", &f); + path myPath(f); + std::string meshFilename = + myPath.parent_path().directory_string() + "/meshDistributor.ser"; + + + int tsModulo = -1; + GET_PARAMETER(0, probVec->getName() + "->output->write every i-th timestep", + "%d", &tsModulo); + + probVec->getFileWriterList().push_back(new Serializer<MeshDistributor>(this, meshFilename, tsModulo)); + writeSerializationFile = true; + } int readSerialization = 0; - GET_PARAMETER(0, probVec->getName() + "->input->read serialization", "%d", &readSerialization); + GET_PARAMETER(0, probVec->getName() + "->input->read serialization", "%d", + &readSerialization); if (readSerialization) { - ERROR_EXIT("Must be reimplemented!\n"); -#if 0 std::string filename = ""; GET_PARAMETER(0, probVec->getName() + "->input->serialization filename", &filename); filename += ".p" + lexical_cast<std::string>(mpiRank); - MSG("Start serialization with %s\n", filename.c_str()); + MSG("Start deserialization with %s\n", filename.c_str()); std::ifstream in(filename.c_str()); - deserialize(in); + probVec->deserialize(in); in.close(); -#endif + MSG("Deserialization from file: %s\n", filename.c_str()); + + if (!deserialized) { + GET_PARAMETER(0, probVec->getName() + "->input->serialization filename", &filename); + path myPath(filename); + std::string meshFilename = + myPath.parent_path().directory_string() + "/meshDistributor.ser.p" + + lexical_cast<std::string>(mpiRank); + std::ifstream in(meshFilename.c_str()); + deserialize(in); + in.close(); + MSG("Deserializtion of mesh distributor from file: %s\n", meshFilename.c_str()); + deserialized = true; + } } probStat.push_back(probVec); @@ -475,6 +505,10 @@ namespace AMDiS { mesh->dofCompress(); updateLocalGlobalNumbering(); + + // === Update periodic mapping, if there are periodic boundaries. === + + createPeriodicMap(); } @@ -990,10 +1024,14 @@ namespace AMDiS { // === to \ref otherIntBoundary. It dependes on which rank is respon- === // === sible for this boundary. === - if (BoundaryManager::isBoundaryPeriodic(elInfo->getBoundary(subObj, i))) { + if (BoundaryManager::isBoundaryPeriodic(elInfo->getBoundary(subObj, i))) { // We have found an element that is at an interior, periodic boundary. AtomicBoundary& b = periodicBoundary.getNewAtomic(otherElementRank); b = bound; + if (mpiRank > otherElementRank) + b.rankObj.setReverseMode(b.neighObj, feSpace); + else + b.neighObj.setReverseMode(b.rankObj, feSpace); } else { // We have found an element that is at an interior, non-periodic boundary. if (mpiRank > otherElementRank) { @@ -1927,7 +1965,7 @@ namespace AMDiS { // Send the global indices to the rank on the other side. stdMpi.getSendData(it->first).reserve(dofs.size()); - for (int i = 0; i < static_cast<int>(dofs.size()); i++) + for (unsigned int i = 0; i < dofs.size(); i++) stdMpi.getSendData(it->first).push_back(mapLocalGlobalDofs[*(dofs[i])]); // Receive from this rank the same number of dofs. @@ -1955,14 +1993,14 @@ namespace AMDiS { boundIt->rankObj.el->getNonVertexDofs(feSpace, boundIt->rankObj, tmpdofs); boundIt->rankObj.el->getVertexDofs(feSpace, boundIt->rankObj, tmpdofs); - for (int j = static_cast<int>(tmpdofs.size()) - 1; j >= 0; j--) - dofs.push_back(tmpdofs[j]); + for (unsigned int i = 0; i < tmpdofs.size(); i++) + dofs.push_back(tmpdofs[i]); } // 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(stdMpi.getRecvData(it->first)[j]); + for (int i = 0; i < static_cast<int>(dofs.size()); i++) { + int globalDofIndex = mapLocalGlobalDofs[*(dofs[i])]; + periodicDof[globalDofIndex].insert(stdMpi.getRecvData(it->first)[i]); dofFromRank[globalDofIndex].insert(it->first); } } @@ -2028,9 +2066,11 @@ namespace AMDiS { SerUtil::serialize(out, partitionVec); SerUtil::serialize(out, oldPartitionVec); SerUtil::serialize(out, nRankDofs); + SerUtil::serialize(out, nOverallDofs); myIntBoundary.serialize(out); otherIntBoundary.serialize(out); + periodicBoundary.serialize(out); serialize(out, sendDofs); serialize(out, recvDofs); @@ -2043,6 +2083,7 @@ namespace AMDiS { serialize(out, periodicDof); SerUtil::serialize(out, rstart); + SerUtil::serialize(out, macroElementStructureConsisten); } @@ -2053,6 +2094,7 @@ namespace AMDiS { SerUtil::deserialize(in, partitionVec); SerUtil::deserialize(in, oldPartitionVec); SerUtil::deserialize(in, nRankDofs); + SerUtil::deserialize(in, nOverallDofs); // Create two maps: one from from element indices to the corresponding element // pointers, and one map from Dof indices to the corresponding dof pointers. @@ -2060,20 +2102,24 @@ namespace AMDiS { std::map<int, const DegreeOfFreedom*> dofMap; ElementDofIterator elDofIter(feSpace); TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL); + ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_EVERY_EL_PREORDER); while (elInfo) { Element *el = elInfo->getElement(); elIndexMap[el->getIndex()] = el; - elInfo = stack.traverseNext(elInfo); - elDofIter.reset(el); - do { - dofMap[elDofIter.getDof()] = elDofIter.getDofPtr(); - } while (elDofIter.next()); + if (el->isLeaf()) { + elDofIter.reset(el); + do { + dofMap[elDofIter.getDof()] = elDofIter.getDofPtr(); + } while (elDofIter.next()); + } + + elInfo = stack.traverseNext(elInfo); } myIntBoundary.deserialize(in, elIndexMap); otherIntBoundary.deserialize(in, elIndexMap); + periodicBoundary.deserialize(in, elIndexMap); deserialize(in, sendDofs, dofMap); deserialize(in, recvDofs, dofMap); @@ -2085,6 +2131,7 @@ namespace AMDiS { deserialize(in, vertexDof, dofMap); SerUtil::deserialize(in, rstart); + SerUtil::deserialize(in, macroElementStructureConsisten); deserialized = true; } diff --git a/AMDiS/src/parallel/ParallelDomainBase.h b/AMDiS/src/parallel/ParallelDomainBase.h index c287bdb9..d21dcd68 100644 --- a/AMDiS/src/parallel/ParallelDomainBase.h +++ b/AMDiS/src/parallel/ParallelDomainBase.h @@ -372,12 +372,6 @@ namespace AMDiS { } protected: - /// - ProblemIterationInterface *iterationIF; - - /// - ProblemTimeInterface *timeIF; - /// std::vector<ProblemVec*> probStat; @@ -511,6 +505,9 @@ namespace AMDiS { */ bool deserialized; + /// Denotes whether there exists a filewriter for this object. + bool writeSerializationFile; + /** \brief * Stores the mesh change index. This is used to recognize changes in the mesh * structure (e.g. through refinement or coarsening managers). -- GitLab