C++ mpi module for stochmagnet_main Package
MPI_GridEnvironment.h
1 #ifndef MPI_GridEnvironment_H
2 #define MPI_GridEnvironment_H
3 
4 //inherited class object
5 #include "MPI_Environment.h"
6 
7 //options list header
8 #include "CORE_OptionsList.h"
9 
10 //numeric function headers
11 #include "functions_array.h"
12 #include "functions_grid.h"
13 
33 template<tUCInt N>
35 
36  //attributes
37 public:
38 
39 
40 private :
41 
42  //type of class & super class
45 
46 
47 
48  //number of grids per direction
49  std::array<tMPICoreId,N> mGridSize;
50 
51  //periodicity of grid per direction
52  std::array<tBoolean,N> mGridPeriodicity;
53 
54  //current grid indices
55  std::array<tMPICoreId,N> mIndices;
56 
57 
58 
59 protected:
60  // CONSTRUCTORS
61 
65 
66  }
79  MPI_GridEnvironment(int& argc,char * argv[],const tBoolean& isOpenMPEnabled) : MPI_Environment(argc,argv,isOpenMPEnabled) {
81  this->getWorld()=MPI_COMM_NULL;
82  }
83 
84 
85  // DESTRUCTORS
88  virtual ~MPI_GridEnvironment(void) {
89 
90 
91  }
92 
93 public:
94 
95 
96  //memory management
97  //=================
100  virtual tMemSize getMemorySize() const override{
101  return sizeof(*this)+getContentsMemorySize();
102  }
103 
112  virtual tMemSize getContentsMemorySize() const override {
113  tMemSize mem=SuperClass::getContentsMemorySize();
114  mem+=sizeof(tMPICoreId)*mGridSize.size();
115  mem+=sizeof(tBoolean)*mGridPeriodicity.size();
116  mem+=sizeof(tMPICoreId)*mIndices.size();
117  return mem;
118  }
119 
120 public:
121 
129  inline static CORE_UniquePointer<SelfClass> New(const std::array<tMPICoreId,N>& nCoresPerDirection,
130  int& argc,char * argv[],const tBoolean& isOpenMPEnabled) {
131 
132  CORE_UniquePointer<SelfClass> p(new SelfClass(argc,argv,isOpenMPEnabled),
134 
135  //std::cout<<" world:"<<parent.getWorld()<<" N:"<<((int)N)<<" nCoresPerDirection:"<<core_arrays::toString(nCoresPerDirection)<<" Periodicity:"<<core_arrays::toString(isPeriodicPerDirection)<<"\n";
136 
137  //not periodic per default
138  std::array<tMPIBoolean,N> isPeriodicPerDirection;
139  for(auto& p: isPeriodicPerDirection) p=false;
140 
141  //set the periodicity per option
142  tString gridP="";
143  if (CORE_OptionsList::ReadOption(argc,argv,false,"cores-grid-periodicity",gridP)) {
144  std::vector<tBoolean> Vs;
145  functions_array::parse(gridP,Vs);
146  for(int i=Vs.size();i<N;i++) {
147  Vs.push_back(false);
148  }
149  auto iVs=Vs.cbegin();
150  for(auto& p:isPeriodicPerDirection) {
151  p=(*iVs);
152  iVs++;
153  }
154  }
155 
156  MPI_Cart_create(MPI_COMM_WORLD,
157  (int) N,nCoresPerDirection.data(),isPeriodicPerDirection.data(),
158  true,
159  &p->getWorld());
160 
161  if (p->getWorld()==MPI_COMM_NULL) {
162  //process can not be added in the grid environement
163  p.reset();
164  return p;
165  }
166  p->initialize();
167  return p;
168 
169  };
170 protected :
171 
172 
173 
174  //accessor methods
175  //================
176 
177 
178 public:
179 
180 
181  //Grid number & grid indices
182  //============================
183 
188  template<typename Q>
189  inline void setGridSize(const std::array<Q,N>& Ns) {
190  const Q* iNs=Ns.data();
191  for(auto& Nk:mGridSize) {
192  Nk=(*iNs);
193  iNs++;
194  }
195  }
196 
197 
200  inline const std::array<tMPICoreId,N>& getGridSize() const {
201  return mGridSize;
202  }
203 
208  template<typename Q>
209  inline void setIndices(const std::array<Q,N>& indices) {
210  const Q* iIs=indices.data();
211  for(auto& Ik:mIndices) {
212  Ik=(*iIs);
213  iIs++;
214  }
215  }
216 
219  inline const std::array<tMPICoreId,N>& getIndices() const {
220  return mIndices;
221  }
222 
223  //neighbors data
224  //===============
225 
226 
227 public:
228 
229 
230 
231 
232 public:
238  inline static tMPIError ComputeGridSize(const MPI_Environment& parent,std::array<tMPICoreId,N>& coresNumber) {
239  int nAvailableCores=parent.getCoresNumber();
240  return ComputeGridSize(nAvailableCores,coresNumber);
241  }
247  inline static tMPIError ComputeGridSize(const tMPICoreId& nAvailableCores,std::array<tMPICoreId,N>& coresNumber) {
248 
249  //number o f needed grids
250  int nGrids=1;
251  for(const auto& Ck:coresNumber) nGrids*=Ck;
252 
253  if (nGrids==0) {
254  //one dimension is free
255  return MPI_Dims_create(nAvailableCores,N,coresNumber.data());
256  } else {
257  //reduce the number of avalaible core
258  return MPI_Dims_create(nGrids,N,coresNumber.data());
259  }
260  }
261 
262 
263 
277  inline static tBoolean ComputeGridSize(const std::array<tReal,N>& Hs,const std::array<tInteger,N>& Ns,
278  const tMPICoreId& nCores,std::array<tMPICoreId,N>& Gs){
279 
280  tUCInt k;
281  // set local constants
282  std::array<tReal,N> invLs;
283  for(k=0;k<N;k++) invLs[k]=1./(Hs[k]*Ns[k]);
284 
285  //divisor of nCores : i such that nCores%i=0
286  std::valarray<tMPICoreId> divisors(nCores);
287 
288 
289  // find all the divisors of nCores
290  tMPICoreId *iDivisors=&divisors[0];
291  for (tMPICoreId i=1;i<=nCores;i++){
292  if ((nCores%i)==0){//i divides nCores
293  (*iDivisors)=i;
294  iDivisors++;
295  }
296  }
297  //number of divisors of nCores
298  tMPICoreId nDivisors=(iDivisors-&divisors[0]);
299 
300 
301  tReal surfaceVolume=0.0;
302  tReal minSurfaceVolume=functions_numeric::getInfinity<tReal>();
303 
304  //Gsample : sample for divisor combination of size N
305  std::array<tMPICoreId,N> GSample;
306  tMPICoreId *iGSample=GSample.data();
307  const tMPICoreId *eGSample=iGSample;eGSample+=N;
308 
309  //number of combinaisons per direction
310  std::array<tInteger,N> GNSamples;//=nDivisors
311  for(auto& GNS:GNSamples) GNS=nDivisors;
312 
313  //GIndices
314  std::array<tInteger,N> GIndices;//index of divisor
315  const tInteger *iGIndices=GIndices.data();;
316  //GIndices=0
317  memset(GIndices.data(),0,N*sizeof(tInteger));
318 
319  do {//loop on samples
320 
321  //Gsample[i]=divisor[GIndices[i]]
322  iGIndices=GIndices.data();
323  iGSample=GSample.data();
324  while (iGSample!=eGSample) {
325  (*iGSample)=divisors[(*iGIndices)];
326  //iterators at next direction
327  iGIndices++;
328  iGSample++;
329  }
330  //test the GSample: 1. prod_k Gsample[k]=nCores
331  if (functions_array::product(GSample)==nCores) {
332  //2. minimize: S/V
333  surfaceVolume=2.0*functions_array::scalarProduct(invLs,GSample);
334 
335  if (surfaceVolume <minSurfaceVolume) {
336  //minimize the surface/volume value
337  minSurfaceVolume=surfaceVolume;
338  Gs=GSample;
339  //std::cout<<"Grid("<<functions_array::toString(GSample)<<")="<<surfaceVolume<<"\n";
340  }
341  }
342 
343  //next indices of sample
344  } while (functions_grid::hasNextElement(GNSamples,GIndices));
345  return true;
346  }
347 
348 
349 
350  //periodic data
351  //=============
352 public:
353 
356  inline const std::array<tBoolean,N>& getGridPeriodicity() const {
357  return mGridPeriodicity;
358  }
359 
363  inline const tBoolean& isPeriodic(const tUCInt& k) const {
364  return mGridPeriodicity[k];
365  }
366 
372  template<typename Q>
373  inline void setGridPeriodicity(const std::array<Q,N>& Ts) {
374  const Q* iTs=Ts.data();
375  for(auto& Tk:mGridPeriodicity) {
376  Tk=(tBoolean) (*iTs);
377  iTs++;
378  }
379  }
380 
381 
382 
388  virtual void initialize() {
389 
391 
392  //initialize the grids number, grids periodicity & grid indices
393  std::array<tMPICoreId,N> nGrids;
394  std::array<tMPIBoolean,N> periodicity;
395  std::array<tMPICoreId,N> indices;
396 
397  // get:
398  // - the grid number per direction
399  // - the periodicity per direction
400  // - teh indices of the current grid per diercton
401  MPI_Cart_get(this->getWorld(),N,nGrids.data(),periodicity.data(),indices.data());
402 
403  //set the number of grid
404  this->setGridSize(nGrids);
405  //set the indices of the current grid
406  this->setIndices(indices);
407  //set if the common grid are periodical
408  this->setGridPeriodicity(periodicity);
409 
410 
411  }
412 
413 
419  inline tMPIError getCoreIdAtIndices(const std::array<tMPICoreId,N>& indices,tMPICoreId& coreId) const {
420  return MPI_Cart_rank(this->getWorld(),indices.data(),&coreId);
421  }
422 
428  inline tMPIError getCoreIndices(const tMPICoreId& coreId,std::array<tMPICoreId,N>& indices) const {
429  return MPI_Cart_coords(this->getWorld(),coreId,N,indices.data());
430  }
431 
432 
433 
434 };
435 
436 
437 #endif
class Free introduced for deleting a smart pointer
Definition: CORE_Object.h:113
static tBoolean ReadOption(int nArgs, char *argv[], const tBoolean &isCaseSensitive, const tString &optionName, tString &optionValue)
read the only the option with optionName in command line
Definition: CORE_OptionsList.cpp:260
This class is a Environment class to define MPI world.
Definition: MPI_Environment.h:36
const tMPICoreId & getCoresNumber() const
get the number of cores of this environment of common environment
Definition: MPI_Environment.h:180
void setIsRootEnvironment(const tBoolean &isRoot)
set true when the environemnt created is a root one but not a common world
Definition: MPI_Environment.h:156
const tMPIComm & getWorld() const
get the world of the environment for reading
Definition: MPI_Environment.h:165
virtual tMemSize getContentsMemorySize() const override
return the memory size of the included associations
Definition: MPI_Environment.h:148
virtual void initialize()
initialize the environment Sets the cores number and the core id of the environment
Definition: MPI_Environment.h:103
This class is a grid Environment of templated dimension N=1,2,3.
Definition: MPI_GridEnvironment.h:34
const std::array< tMPICoreId, N > & getGridSize() const
get the grids number
Definition: MPI_GridEnvironment.h:200
virtual ~MPI_GridEnvironment(void)
destroy
Definition: MPI_GridEnvironment.h:88
tMPIError getCoreIndices(const tMPICoreId &coreId, std::array< tMPICoreId, N > &indices) const
get the indices of the core with coreId
Definition: MPI_GridEnvironment.h:428
tMPIError getCoreIdAtIndices(const std::array< tMPICoreId, N > &indices, tMPICoreId &coreId) const
the core id within the grid at indices
Definition: MPI_GridEnvironment.h:419
const std::array< tBoolean, N > & getGridPeriodicity() const
return the periodicity of the grid
Definition: MPI_GridEnvironment.h:356
const std::array< tMPICoreId, N > & getIndices() const
get the indices of the current core within the grid environment
Definition: MPI_GridEnvironment.h:219
static tBoolean ComputeGridSize(const std::array< tReal, N > &Hs, const std::array< tInteger, N > &Ns, const tMPICoreId &nCores, std::array< tMPICoreId, N > &Gs)
compute the grid size in order to minimize the ratio S/V where S is the surface of 1 cpu block and V ...
Definition: MPI_GridEnvironment.h:277
void setIndices(const std::array< Q, N > &indices)
set the indices of the current core
Definition: MPI_GridEnvironment.h:209
static tMPIError ComputeGridSize(const MPI_Environment &parent, std::array< tMPICoreId, N > &coresNumber)
get the cores number per direction if possible
Definition: MPI_GridEnvironment.h:238
void setGridPeriodicity(const std::array< Q, N > &Ts)
set grid periodicity
Definition: MPI_GridEnvironment.h:373
void setGridSize(const std::array< Q, N > &Ns)
get the grids number
Definition: MPI_GridEnvironment.h:189
MPI_GridEnvironment()
create a root environment
Definition: MPI_GridEnvironment.h:64
static CORE_UniquePointer< SelfClass > New(const std::array< tMPICoreId, N > &nCoresPerDirection, int &argc, char *argv[], const tBoolean &isOpenMPEnabled)
create a new cart environment
Definition: MPI_GridEnvironment.h:129
virtual void initialize()
initialize the environment
Definition: MPI_GridEnvironment.h:388
MPI_GridEnvironment(int &argc, char *argv[], const tBoolean &isOpenMPEnabled)
create a root environment
Definition: MPI_GridEnvironment.h:79
virtual tMemSize getMemorySize() const override
return the memory size of the class
Definition: MPI_GridEnvironment.h:100
virtual tMemSize getContentsMemorySize() const override
return the memory size of the included associations
Definition: MPI_GridEnvironment.h:112
static tMPIError ComputeGridSize(const tMPICoreId &nAvailableCores, std::array< tMPICoreId, N > &coresNumber)
get the cores number per direction if possible
Definition: MPI_GridEnvironment.h:247
const tBoolean & isPeriodic(const tUCInt &k) const
return true if the grid is periodic in direction k
Definition: MPI_GridEnvironment.h:363