// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == crystal growth group == // == == // == Stiftung caesar == // == Ludwig-Erhard-Allee 2 == // == 53175 Bonn == // == germany == // == == // ============================================================================ // == == // == http://www.caesar.de/cg/AMDiS == // == == // ============================================================================ /** \file ParallelDomain.h */ #ifndef AMDIS_PARALLELDOMAIN_H #define AMDIS_PARALLELDOMAIN_H #include #include #include #include "ProblemTimeInterface.h" #include "ProblemIterationInterface.h" #include "FiniteElemSpace.h" #include "AdaptInfo.h" #include "InteriorBoundary.h" #include "AMDiS_fwd.h" #include "petsc.h" #include "petscsys.h" #include "petscao.h" #include "mpi.h" namespace AMDiS { class ParMetisPartitioner; class ParallelDomainBase : public ProblemIterationInterface, public ProblemTimeInterface { private: /// Defines type for a vector of DOFs. typedef std::vector DofContainer; /// Defines a mapping type from DOFs to rank numbers. typedef std::map DofToRank; /// Defines a mapping type from DOFs to a set of rank numbers. typedef std::map > DofToPartitions; /// Defines a mapping type from rank numbers to sets of DOFs. typedef std::map RankToDofContainer; /// Defines a mapping type from DOF indices to DOF indices. typedef std::map DofMapping; /// Defines a mapping type from DOF indices to boolean values. typedef std::map DofToBool; /// Defines a mapping type from rank numbers to sets of coordinates. typedef std::map > > RankToCoords; /// Forward type (it maps rank numbers to the interior boundary objects). typedef InteriorBoundary::RankToBoundMap RankToBoundMap; public: ParallelDomainBase(const std::string& name, ProblemIterationInterface *iterationIF, ProblemTimeInterface *timeIF, FiniteElemSpace *feSpace, RefinementManager *refineManager); virtual ~ParallelDomainBase() {} virtual void initParallelization(AdaptInfo *adaptInfo); void exitParallelization(AdaptInfo *adaptInfo); /** \brief * Test, if the mesh consists of macro elements only. The mesh partitioning of * the parallelization works for macro meshes only and would fail, if the mesh * is already refined in some way. Therefore, this function will exit the program * if it finds a non macro element in the mesh. */ void testForMacroMesh(); /// Set for each element on the partitioning level the number of leaf elements. double setElemWeights(AdaptInfo *adaptInfo); void partitionMesh(AdaptInfo *adaptInfo); virtual void setTime(AdaptInfo *adaptInfo) {} virtual void initTimestep(AdaptInfo *adaptInfo) {} virtual void closeTimestep(AdaptInfo *adaptInfo) {} virtual void solveInitialProblem(AdaptInfo *adaptInfo) {} virtual void transferInitialSolution(AdaptInfo *adaptInfo) {} virtual void beginIteration(AdaptInfo *adaptInfo) { iterationIF->beginIteration(adaptInfo); } virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION) { ERROR_EXIT("Not implemented!\n"); return 0; } virtual void endIteration(AdaptInfo *adaptInfo) { iterationIF->endIteration(adaptInfo); } virtual int getNumProblems() { return 0; } inline virtual const std::string& getName() { return name; } /// Returns \ref nRankDOFs, the number of DOFs in the rank mesh. int getNumberRankDOFs() { return nRankDOFs; } void fillPetscMatrix(DOFMatrix *mat, DOFVector *vec); void solvePetscMatrix(DOFVector *vec); virtual ProblemStatBase *getProblem(int number = 0) { return NULL; } virtual void serialize(std::ostream&) {} virtual void deserialize(std::istream&) {} protected: /** \brief * Determine the interior boundaries, i.e. boundaries between ranks, and store * all information about them in \ref interiorBoundary. */ void createInteriorBoundaryInfo(DofContainer& rankDOFs, DofToRank& boundaryDOFs); /// Removes all macro elements from the mesh that are not part of ranks partition. void removeMacroElements(); /** \brief * Creates from a macro mesh a correct local and global DOF index numbering. * * \param[out] rankDOFs Returns all DOFs from the macro mesh, which are owned * by the rank after partitioning the macro mesh. * \param[out] boundaryDOFs Returns all DOFs from the macro mesh, which lies at * an interior boundary of the rank. This object maps * each such DOF to the rank that owns this DOF. * \param[out] nRankDOFs Number of DOFs owned by rank. * \param[out] nOverallDOFs Number of all DOFs in macro mesh. */ void createLocalGlobalNumbering(DofContainer& rankDOFs, DofToRank& boundaryDOFs, int& nRankDOFs, int& nOverallDOFs); void updateLocalGlobalNumbering(int& nRankDOFs, int& nOverallDOFs); void addAllVertexDOFs(Element *el, int ithEdge, DofContainer& dofs); void addAllEdgeDOFs(Element *el, int ithEdge, DofContainer& dofs); /** \brief * This function traverses the whole mesh, i.e. before it is really partitioned, * and collects information about which DOF corresponds to which rank. Can only * be used, if \ref partitionVec is set correctly. This is only the case, when * the macro mesh is partitioned. * * \param[out] partionDOFs Stores to each DOF pointer the set of ranks the DOF is * part of. * \param[out] rankDOFs Stores all rank DOFs. * \param[out] boundaryDOFs Stores all DOFs in ranks partition that are on an * interior boundary but correspond to another rank. */ void createDOFMemberInfo(DofToPartitions& partitionDOFs, DofContainer& rankDOFs, DofToRank& boundaryDOFs); void DbgTestInteriorBoundary(); /** \brief * This function is used for debugging only. It traverses all interior boundaries * and compares the dof indices on them with the dof indices of the boundarys * neighbours. The function fails, when dof indices on an interior boundary does * not fit together. */ void DbgTestCommonDofs(); protected: /// ProblemIterationInterface *iterationIF; /// ProblemTimeInterface *timeIF; /// The rank of the current process. int mpiRank; /// Overall number of processes. int mpiSize; /** \brief * MPI communicator collected all processes, which should * be used for calculation. The Debug procces is not included * in this communicator. */ MPI::Intracomm mpiComm; /// Name of the problem (as used in the init files) std::string name; /// Finite element space of the problem. FiniteElemSpace *feSpace; /// Mesh of the problem. Mesh *mesh; /// Info level. int info; /// Refinement manager for the mesh. RefinementManager *refinementManager; /// Pointer to the paritioner which is used to devide a mesh into partitions. ParMetisPartitioner *partitioner; /// Weights for the elements, i.e., the number of leaf elements within this element. std::map elemWeights; /// Is true, if the mesh was not partitioned before, otherwise it's false. bool initialPartitionMesh; /** \brief * Stores to every coarse element index the number of the partition it * corresponds to. */ std::map partitionVec; /** \brief * Stores an old partitioning of elements. To every element index the number * of the parition it corresponds to is stored. */ std::map oldPartitionVec; Mat petscMatrix; Vec petscRhsVec; Vec petscSolVec; /// Number of DOFs in the rank mesh. int nRankDOFs; /** \brief * Set of all interior boundary DOFs in ranks partition. The object maps to * each such DOF to the number of the rank that owns this DOF. */ DofToRank boundaryDOFs; /** \brief * Defines the interior boundaries of the domain that result from partitioning * the whole mesh. Contains only the boundaries, which are owned by the rank, i.e., * the object gives for every neighbour rank i the boundaries this rank owns and * shares with rank i. */ InteriorBoundary myIntBoundary; /** \brief * Defines the interior boundaries of the domain that result from partitioning * the whole mesh. Contains only the boundaries, which are not owned by the rank, * i.e., the object gives for every neighbour rank i the boundaries that are * owned by rank i and are shared with this rank. */ InteriorBoundary otherIntBoundary; /** \brief * This map contains for each rank the list of dofs the current rank must send * to exchange solution dofs at the interior boundaries. */ RankToDofContainer sendDofs; /** \brief * This map contains for each rank the list of dofs from which the current rank * must receive solution values of dofs at the interior boundaries. */ RankToDofContainer recvDofs; /// Maps local to global dof indices. DofMapping mapLocalGlobalDOFs; /// Maps global to local dof indices. DofMapping mapGlobalLocalDOFs; /** \brief * Maps all DOFs in ranks partition to a bool value. If it is true, the DOF is * owned by the rank. Otherwise, its an interior boundary DOF that is owned by * another rank. */ DofToBool isRankDOF; }; class ParallelDomainScal : public ParallelDomainBase { public: ParallelDomainScal(const std::string& name, ProblemScal *problem, ProblemInstatScal *problemInstat); void initParallelization(AdaptInfo *adaptInfo); virtual Flag oneIteration(AdaptInfo *adaptInfo, Flag toDo = FULL_ITERATION); protected: /// Starts the solution of the linear system using Petsc. void solve(); protected: /// Pointer to the stationary problem. ProblemScal *probScal; }; } #endif // AMDIS_PARALLELDOMAIN_H