Line data Source code
1 : // Copyright (C) 2015 Technische Universitaet Muenchen 2 : // This file is part of the Mamico project. For conditions of distribution 3 : // and use, please see the copyright notice in Mamico's main folder, or at 4 : // www5.in.tum.de/mamico 5 : #ifndef _MOLECULARDYNAMICS_COUPLING_PARALLELTOPOLOGY_ZYXTOPOLOGY_H_ 6 : #define _MOLECULARDYNAMICS_COUPLING_PARALLELTOPOLOGY_ZYXTOPOLOGY_H_ 7 : 8 : #include "coupling/CouplingMDDefinitions.h" 9 : #include "coupling/paralleltopology/ParallelTopology.h" 10 : 11 : namespace coupling { 12 : namespace paralleltopology { 13 : template <unsigned int dim> class ZYXTopology; 14 : } 15 : } // namespace coupling 16 : 17 : /** In the ZYXTopology, the process coordinates convert to a rank as 18 : * rank = x*ny*nz + y*nz + z = z + nz*(y+ny*x) (for 3D). 19 : * topologyOffset is used for linearized access of multiple MD instances. 20 : * Derived class from the class ParallelTopology. E.g. assuming 21 : * ParallelTopologyType = XYZ and there is a cubic domain, splitted into 8 22 : * sub-domains (2 sub-domains in each dimension). Then the ordering of the MPI 23 : * processes is: Rank=0 for x=0,y=0,z=0. Rank=1 for x=0,y=0,z=1. Rank=2 for 24 : * x=0,y=1,z=0. Rank=3 for x=0,y=1,z=1. Rank=4 for x=1,y=0,z=0. Rank=5 for 25 : * x=1,y=0,z=1. Rank=6 for x=1,y=1,z=0. Rank=7 for x=1,y=1,z=1. 26 : * @brief The ZYXTopology orders the ranks in z-y-x manner. 27 : * @tparam dim Number of dimensions; it can be 1, 2 or 3 28 : * @author Philipp Neumann 29 : * @todo Philipp could you please take a look on this class 30 : */ 31 : template <unsigned int dim> class coupling::paralleltopology::ZYXTopology : public coupling::paralleltopology::ParallelTopology<dim> { 32 : public: 33 : /** Constructor */ 34 24 : ZYXTopology(tarch::la::Vector<dim, unsigned int> numberProcesses) 35 48 : : coupling::paralleltopology::ParallelTopology<dim>(), _numberProcesses(numberProcesses), 36 48 : _divisionFactor4NumberProcesses(initDivisionFactor(numberProcesses)) {} 37 : 38 : /** Destructor */ 39 24 : virtual ~ZYXTopology() {} 40 : 41 560 : tarch::la::Vector<dim, unsigned int> getProcessCoordinates(unsigned int rank, unsigned int topologyOffset) const { 42 560 : tarch::la::Vector<dim, unsigned int> processCoordinates(0); 43 560 : unsigned int help = rank - topologyOffset; 44 2160 : for (unsigned int d = 0; d < dim; d++) { 45 1600 : processCoordinates[d] = help / _divisionFactor4NumberProcesses[d]; 46 1600 : help = help - processCoordinates[d] * _divisionFactor4NumberProcesses[d]; 47 : } 48 : #if (COUPLING_MD_DEBUG == COUPLING_MD_YES) 49 : std::cout << "Rank=" << rank << " corresponds to process coordinates=" << processCoordinates << std::endl; 50 : #endif 51 560 : return processCoordinates; 52 : } 53 : 54 : /** computes the rank as shown above, see second formula of class definition 55 : */ 56 144 : unsigned int getRank(tarch::la::Vector<dim, unsigned int> processCoordinates, unsigned int topologyOffset) const { 57 144 : unsigned int rank = processCoordinates[0]; 58 408 : for (unsigned int d = 1; d < dim; d++) { 59 264 : rank = rank * _numberProcesses[d] + processCoordinates[d]; 60 : } 61 144 : return rank + topologyOffset; 62 : } 63 : 64 : private: 65 : /** sets the division factor for each vector entry. For ZYX, this corresponds 66 : * to (in 3D) (ny*nz,nz,1) and to (2D) (ny,1). */ 67 24 : tarch::la::Vector<dim, unsigned int> initDivisionFactor(tarch::la::Vector<dim, unsigned int> numberProcesses) const { 68 24 : tarch::la::Vector<dim, unsigned int> div(1); 69 60 : for (int d = dim - 2; d > -1; d--) { 70 36 : div[d] = div[d + 1] * numberProcesses[d + 1]; 71 : } 72 24 : return div; 73 : } 74 : 75 : /* number of processes */ 76 : const tarch::la::Vector<dim, unsigned int> _numberProcesses; 77 : /* division factor */ 78 : const tarch::la::Vector<dim, unsigned int> _divisionFactor4NumberProcesses; 79 : }; 80 : #endif // _MOLECULARDYNAMICS_COUPLING_PARALLELTOPOLOGY_ZYXTOPOLOGY_H_