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_
|