source: XIOS/dev/dev_olga/src/distribution_client.cpp @ 1132

Last change on this file since 1132 was 1129, checked in by mhnguyen, 7 years ago

Updating two-level server.
Each client now can play the role of server: It can forward data to other clients or write data like a server.
Each client must combine all data received from other client(s) before forward them or write them on files

+) Correct some bugs of exchange data_index in domain and axis
+) Reorder some functions in context.cpp to make sure that all necessary attributes are available before computing index
+) Add the mapping index for client to write data.

Test
+) On Curie
+) test_client and test_complete
+) Mode:

  • Only one level: Correct
  • Two levels: Work if using ddt (bug)

+) Only zoom is tested but other transformations should work
+) No reading test

File size: 26.3 KB
Line 
1/*!
2   \file distribution_client.cpp
3   \author Ha NGUYEN
4   \since 13 Jan 2015
5   \date 09 Mars 2015
6
7   \brief Index distribution on client side.
8 */
9#include "distribution_client.hpp"
10
11namespace xios {
12
13CDistributionClient::CDistributionClient(int rank, CGrid* grid, const GlobalLocalDataMap& globalLocalIndex)
14  : CDistribution(rank, 0)
15   , axisDomainOrder_()
16   , nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_(),nZoomBegin_(), nZoomEnd_()
17   , dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_(), domainMasks_(), axisMasks_()
18   , gridMask_(), indexMap_()
19   , isDataDistributed_(true), axisNum_(0), domainNum_(0)
20   , localDataIndex_(), localMaskIndex_()
21   , globalLocalDataSendToServerMap_(globalLocalIndex)
22   , infoIndex_(), isComputed_(false)
23   , elementLocalIndex_(), elementGlobalIndex_(), elementIndexData_()
24   , elementZoomMask_(), elementNLocal_(), elementNGlobal_()
25{
26  isComputed_ = true;
27  localDataIndex_.resize(globalLocalIndex.size());
28  localMaskIndex_.resize(globalLocalIndex.size());
29  GlobalLocalDataMap::const_iterator it = globalLocalIndex.begin(), ite = globalLocalIndex.end();
30  int idx = 0;
31  for (; it!=ite; ++it)
32  {
33    localMaskIndex_[idx] = localDataIndex_[idx] = it->second;
34    ++idx;
35  }
36
37  std::vector<CDomain*> domList = grid->getDomains();
38  std::vector<CAxis*> axisList = grid->getAxis();
39  std::vector<CScalar*> scalarList = grid->getScalars();
40  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
41
42  int numElement = axisDomainOrder.numElements();
43  // Because domain and axis can be in any order (axis1, domain1, axis2, axis3, )
44  // their position should be specified. In axisDomainOrder, domain == true, axis == false
45  int dims = numElement;
46  idx = 0;
47  std::vector<int> indexMap(numElement); 
48  for (int i = 0; i < numElement; ++i)
49  {
50    indexMap[i] = idx;
51    if (2 == axisDomainOrder(i))
52    {
53      ++dims;
54      idx += 2;
55    }
56    else ++idx;
57  }
58
59  nGlob_.resize(dims);
60
61  // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
62  dataNIndex_.resize(numElement);
63  dataDims_.resize(numElement);
64  isDataDistributed_ = false;
65  int domIndex = 0, axisIndex = 0, scalarIndex = 0;
66  for (idx = 0; idx < numElement; ++idx)
67  {
68    int eleDim = axisDomainOrder(idx);
69
70    // If this is a domain
71    if (2 == eleDim)
72    {
73      // On the j axis
74      nGlob_.at(indexMap[idx]+1)  = domList[domIndex]->nj_glo.getValue();
75      nGlob_.at(indexMap[idx]) = domList[domIndex]->ni_glo.getValue();
76      dataNIndex_.at(idx) = domList[domIndex]->data_i_index.numElements();
77      dataDims_.at(idx) = domList[domIndex]->data_dim.getValue();
78
79      isDataDistributed_ |= domList[domIndex]->isDistributed();
80      ++domIndex;
81    }
82    else if (1 == eleDim)// So it's an axis
83    {
84      nGlob_.at(indexMap[idx]) = axisList[axisIndex]->n_glo.getValue();
85      dataNIndex_.at(idx) = axisList[axisIndex]->data_index.numElements();
86      dataDims_.at(idx) = 1;
87
88      isDataDistributed_ |= axisList[axisIndex]->isDistributed();
89      ++axisIndex;
90    }
91    else // scalar
92    {
93      nGlob_.at(indexMap[idx]) = 1;
94      dataNIndex_.at(idx) = 1;
95      dataDims_.at(idx) = 1;
96
97      isDataDistributed_ |= false;
98      ++scalarIndex;
99    }
100  }
101
102}
103
104CDistributionClient::CDistributionClient(int rank, int dims, const CArray<size_t,1>& globalIndex)
105   : CDistribution(rank, dims, globalIndex)
106   , axisDomainOrder_()
107   , nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_(),nZoomBegin_(), nZoomEnd_()
108   , dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_(), domainMasks_(), axisMasks_()
109   , gridMask_(), indexMap_()
110   , isDataDistributed_(true), axisNum_(0), domainNum_(0)
111   , localDataIndex_(), localMaskIndex_()
112   , globalLocalDataSendToServerMap_()
113   , infoIndex_(), isComputed_(false)
114   , elementLocalIndex_(), elementGlobalIndex_(), elementIndexData_()
115   , elementZoomMask_(), elementNLocal_(), elementNGlobal_()
116{
117}
118
119CDistributionClient::CDistributionClient(int rank, CGrid* grid)
120   : CDistribution(rank, 0)
121   , axisDomainOrder_()
122   , nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_(),nZoomBegin_(), nZoomEnd_()
123   , dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_(), domainMasks_(), axisMasks_()
124   , gridMask_(), indexMap_()
125   , isDataDistributed_(true), axisNum_(0), domainNum_(0)
126   , localDataIndex_(), localMaskIndex_()
127   , globalLocalDataSendToServerMap_()
128   , infoIndex_(), isComputed_(false)
129   , elementLocalIndex_(), elementGlobalIndex_(), elementIndexData_()
130   , elementZoomMask_(), elementNLocal_(), elementNGlobal_()
131{
132  readDistributionInfo(grid);
133  createGlobalIndex();
134}
135
136CDistributionClient::~CDistributionClient()
137{ /* Nothing to do */ }
138
139/*!
140  Read information of a grid to generate distribution.
141  Every grid is composed of several axis or/and domain(s). Their information are processed
142stored and used to calculate index distribution between client and server
143  \param [in] grid Grid to read
144*/
145void CDistributionClient::readDistributionInfo(CGrid* grid)
146{
147  std::vector<CDomain*> domList = grid->getDomains();
148  std::vector<CAxis*> axisList = grid->getAxis();
149  std::vector<CScalar*> scalarList = grid->getScalars();
150  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
151
152  readDistributionInfo(domList, axisList, scalarList, axisDomainOrder);
153
154  // Then check mask of grid
155  int gridDim = domList.size() * 2 + axisList.size();
156  grid->checkMask();
157  switch (gridDim) {
158    case 0:
159      gridMask_.resize(1);
160      gridMask_(0) = true;
161      break;
162    case 1:
163      readGridMaskInfo(grid->mask_1d);
164      break;
165    case 2:
166      readGridMaskInfo(grid->mask_2d);
167      break;
168    case 3:
169      readGridMaskInfo(grid->mask_3d);
170      break;
171    case 4:
172      readGridMaskInfo(grid->mask_4d);
173      break;
174    case 5:
175      readGridMaskInfo(grid->mask_5d);
176      break;
177    case 6:
178      readGridMaskInfo(grid->mask_6d);
179      break;
180    case 7:
181      readGridMaskInfo(grid->mask_7d);
182      break;
183    default:
184      break;
185  }
186}
187
188/*!
189  Read information from domain(s) and axis to generate distribution.
190  All information related to domain, e.g ibegin, jbegin, ni, nj, ni_glo, nj_glo
191as well as related to axis, e.g dataNIndex, dataIndex will be stored to compute
192the distribution between clients and servers. Till now, every data structure of domain has been kept
193like before, e.g: data_n_index to make sure a compability, however, it should be changed?
194  \param [in] domList List of domains of grid
195  \param [in] axisList List of axis of grid
196  \param [in] scalarList List of scalar of grid
197  \param [in] axisDomainOrder order of axis and domain inside a grid. 2 if domain, 1 if axis and zero if scalar
198//  \param [in] gridMask Mask of grid, for now, keep it 3 dimension, but it needs changing
199*/
200void CDistributionClient::readDistributionInfo(const std::vector<CDomain*>& domList,
201                                               const std::vector<CAxis*>& axisList,
202                                               const std::vector<CScalar*>& scalarList,
203                                               const CArray<int,1>& axisDomainOrder)
204{
205  domainNum_ = domList.size();
206  axisNum_   = axisList.size();
207  numElement_ = axisDomainOrder.numElements(); // Number of element, e.x: Axis, Domain
208
209  axisDomainOrder_.resize(numElement_);
210  axisDomainOrder_ = axisDomainOrder;
211
212  // Each domain or axis has its mask, of course
213  domainMasks_.resize(domainNum_);
214  for (int i = 0; i < domainNum_;++i)
215  {
216    domainMasks_[i].resize(domList[i]->mask_1d.numElements());
217    domainMasks_[i] = domList[i]->mask_1d;
218  }
219
220  axisMasks_.resize(axisNum_);
221  for (int i = 0; i < axisNum_; ++i)
222  {
223    axisMasks_[i].resize(axisList[i]->mask.numElements());
224    axisMasks_[i] = axisList[i]->mask;
225  }
226
227  // Because domain and axis can be in any order (axis1, domain1, axis2, axis3, )
228  // their position should be specified. In axisDomainOrder, domain == true, axis == false
229  int idx = 0;
230  indexMap_.resize(numElement_);
231  this->dims_ = numElement_;
232  for (int i = 0; i < numElement_; ++i)
233  {
234    indexMap_[i] = idx;
235    if (2 == axisDomainOrder(i))
236    {
237      ++(this->dims_);
238      idx += 2;
239    }
240    else ++idx;
241  }
242
243  // Size of each dimension (local and global)
244  nLocal_.resize(this->dims_);
245  nGlob_.resize(this->dims_);
246  nBeginLocal_.resize(this->dims_,0);
247  nBeginGlobal_.resize(this->dims_,0);
248  nZoomBegin_.resize(this->dims_);
249  nZoomEnd_.resize(this->dims_);
250
251  // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
252  dataNIndex_.resize(numElement_);
253  dataDims_.resize(numElement_);
254  dataBegin_.resize(this->dims_);
255
256  // Data_*_index of each dimension
257  dataIndex_.resize(this->dims_);
258  infoIndex_.resize(this->dims_);
259
260  elementLocalIndex_.resize(numElement_);
261  elementGlobalIndex_.resize(numElement_);
262  elementIndexData_.resize(numElement_);
263  elementZoomMask_.resize(numElement_);
264  elementNLocal_.resize(numElement_);
265  elementNGlobal_.resize(numElement_);
266
267  elementNLocal_[0] = 1;
268  elementNGlobal_[0] = 1;
269  isDataDistributed_ = false;
270
271  size_t localSize = 1, globalSize = 1;
272
273  // A trick to determine position of each domain in domainList
274  int domIndex = 0, axisIndex = 0, scalarIndex = 0;
275  idx = 0;
276
277 
278  // Update all the vectors above
279  for (idx = 0; idx < numElement_; ++idx)
280  {
281    int eleDim = axisDomainOrder(idx);
282    elementNLocal_[idx] = localSize;
283    elementNGlobal_[idx] = globalSize;
284
285    // If this is a domain
286    if (2 == eleDim)
287    {
288      // On the j axis
289      nLocal_.at(indexMap_[idx]+1) = domList[domIndex]->nj.getValue();
290      nGlob_.at(indexMap_[idx]+1)  = domList[domIndex]->nj_glo.getValue();
291      nBeginLocal_.at(indexMap_[idx]+1) = 0;
292      nBeginGlobal_.at(indexMap_[idx]+1) = domList[domIndex]->jbegin;
293      nZoomBegin_.at((indexMap_[idx]+1)) = 0; //domList[domIndex]->global_zoom_jbegin;
294      nZoomEnd_.at((indexMap_[idx]+1))   = domList[domIndex]->nj_glo.getValue()- 1; //domList[domIndex]->global_zoom_jbegin + domList[domIndex]->global_zoom_nj-1;
295
296      dataBegin_.at(indexMap_[idx]+1) = domList[domIndex]->data_jbegin.getValue();
297      dataIndex_.at(indexMap_[idx]+1).reference(domList[domIndex]->data_j_index);
298      infoIndex_.at(indexMap_[idx]+1).reference(domList[domIndex]->j_index);
299
300      // On the i axis
301      nLocal_.at(indexMap_[idx]) = domList[domIndex]->ni.getValue();
302      nGlob_.at(indexMap_[idx]) = domList[domIndex]->ni_glo.getValue();
303      nBeginLocal_.at(indexMap_[idx]) = 0;
304      nBeginGlobal_.at(indexMap_[idx]) = domList[domIndex]->ibegin;
305      nZoomBegin_.at((indexMap_[idx])) = 0; // domList[domIndex]->global_zoom_ibegin;
306      nZoomEnd_.at((indexMap_[idx]))   = domList[domIndex]->ni_glo.getValue() -1; //domList[domIndex]->global_zoom_ibegin + domList[domIndex]->global_zoom_ni-1;
307
308      dataBegin_.at(indexMap_[idx]) = domList[domIndex]->data_ibegin.getValue();
309      dataIndex_.at(indexMap_[idx]).reference(domList[domIndex]->data_i_index);
310      infoIndex_.at(indexMap_[idx]).reference(domList[domIndex]->i_index);
311
312      dataNIndex_.at(idx) = domList[domIndex]->data_i_index.numElements();
313      dataDims_.at(idx) = domList[domIndex]->data_dim.getValue();
314
315      isDataDistributed_ |= domList[domIndex]->isDistributed();
316
317      localSize *= nLocal_.at(indexMap_[idx]+1)* nLocal_.at(indexMap_[idx]);
318      globalSize *= nGlob_.at(indexMap_[idx]+1)* nGlob_.at(indexMap_[idx]);
319      ++domIndex;
320    }
321    else if (1 == eleDim)// So it's an axis
322    {
323      nLocal_.at(indexMap_[idx]) = axisList[axisIndex]->n.getValue();
324      nGlob_.at(indexMap_[idx]) = axisList[axisIndex]->n_glo.getValue();
325      nBeginLocal_.at(indexMap_[idx]) = 0;
326      nBeginGlobal_.at(indexMap_[idx]) = axisList[axisIndex]->begin.getValue();
327      nZoomBegin_.at((indexMap_[idx])) = 0; //axisList[axisIndex]->global_zoom_begin;
328      nZoomEnd_.at((indexMap_[idx])) = axisList[axisIndex]->n_glo.getValue() - 1; //axisList[axisIndex]->global_zoom_begin + axisList[axisIndex]->global_zoom_n-1;
329
330      dataBegin_.at(indexMap_[idx]) = axisList[axisIndex]->data_begin.getValue();
331      dataIndex_.at(indexMap_[idx]).reference(axisList[axisIndex]->data_index);
332      infoIndex_.at(indexMap_[idx]).reference(axisList[axisIndex]->index);
333      dataNIndex_.at(idx) = axisList[axisIndex]->data_index.numElements();
334      dataDims_.at(idx) = 1;
335
336      isDataDistributed_ |= axisList[axisIndex]->isDistributed();
337
338      localSize *= nLocal_.at(indexMap_[idx]);
339      globalSize *= nGlob_.at(indexMap_[idx]);
340
341      ++axisIndex;
342    }
343    else // scalar
344    {
345      nLocal_.at(indexMap_[idx]) = 1;
346      nGlob_.at(indexMap_[idx]) = 1;
347      nBeginLocal_.at(indexMap_[idx]) = 0;
348      nBeginGlobal_.at(indexMap_[idx]) = 1;
349      nZoomBegin_.at((indexMap_[idx])) = 0;
350      nZoomEnd_.at((indexMap_[idx])) = 0;
351
352      dataBegin_.at(indexMap_[idx]) = 0;
353      dataIndex_.at(indexMap_[idx]).resize(1); dataIndex_.at(indexMap_[idx])(0) = 0;
354      infoIndex_.at(indexMap_[idx]).resize(1); infoIndex_.at(indexMap_[idx])(0) = 0;
355      dataNIndex_.at(idx) = 1;
356      dataDims_.at(idx) = 1;
357
358      isDataDistributed_ |= false;
359
360      localSize *= nLocal_.at(indexMap_[idx]);
361      globalSize *= nGlob_.at(indexMap_[idx]);
362
363      ++scalarIndex;
364    }
365  }
366}
367
368/*!
369  Create local index of domain(s).
370  A domain can have data index which even contains the "ghost" points. Very often, these
371data surround the true data. In order to send correct data to server,
372a client need to know index of the true data.
373*/
374void CDistributionClient::createLocalDomainDataIndex()
375{
376  int idxDomain = 0;
377  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
378  {
379    if (2 == axisDomainOrder_(i))
380    {
381      elementIndexData_[i].resize(dataNIndex_[i]);
382      elementIndexData_[i] = false;
383      int iIdx, jIdx = 0, count = 0, localIndex;
384      for (int j = 0; j < dataNIndex_[i]; ++j)
385      {
386        iIdx = getDomainIndex((dataIndex_[indexMap_[i]])(j), (dataIndex_[indexMap_[i]+1])(j),
387                              dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
388                              dataDims_[i], nLocal_[indexMap_[i]], jIdx);
389
390        if ((iIdx >= nBeginLocal_[indexMap_[i]]) && (iIdx < nLocal_[indexMap_[i]]) &&
391           (jIdx >= nBeginLocal_[indexMap_[i]+1]) && (jIdx < nLocal_[indexMap_[i]+1]) &&
392           (domainMasks_[idxDomain](iIdx + jIdx*nLocal_[indexMap_[i]])))
393        {
394          ++count;
395          elementIndexData_[i](j) = true;
396        }
397      }
398
399      elementLocalIndex_[i].resize(count);
400      elementGlobalIndex_[i].resize(count);
401      elementZoomMask_[i].resize(count);
402      elementZoomMask_[i] = false;
403      count = 0;
404      CArray<bool,1>& tmpIndexElementData = elementIndexData_[i];
405      CArray<bool,1>& tmpZoomMaskElement = elementZoomMask_[i];
406      CArray<int,1>& tmpLocalElementIndex = elementLocalIndex_[i];
407      CArray<size_t,1>& tmpGlobalElementIndex = elementGlobalIndex_[i];
408      for (int j = 0; j < dataNIndex_[i]; ++j)
409      {
410        if (tmpIndexElementData(j))
411        {
412          iIdx = getDomainIndex((dataIndex_[indexMap_[i]])(j), (dataIndex_[indexMap_[i]+1])(j),
413                                dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
414                                dataDims_[i], nLocal_[indexMap_[i]], jIdx);
415          localIndex = tmpLocalElementIndex(count) = iIdx + jIdx * nLocal_[indexMap_[i]];
416          tmpGlobalElementIndex(count) = (infoIndex_[indexMap_[i]])(localIndex) + ((infoIndex_[indexMap_[i]+1])(localIndex))*nGlob_[indexMap_[i]];
417          if ((((infoIndex_[indexMap_[i]])(localIndex)) <= nZoomEnd_[indexMap_[i]])
418             && (nZoomBegin_[indexMap_[i]] <= ((infoIndex_[indexMap_[i]])(localIndex)))
419             && (((infoIndex_[indexMap_[i]+1])(localIndex)) <= nZoomEnd_[indexMap_[i]+1])
420             && (nZoomBegin_[indexMap_[i]+1] <= ((infoIndex_[indexMap_[i]+1])(localIndex))))
421          {
422            tmpZoomMaskElement(count) = true;
423          }
424          ++count;
425        }
426      }
427      ++idxDomain;
428    }
429  }
430}
431
432/*!
433  Create local index of axis.
434*/
435void CDistributionClient::createLocalAxisDataIndex()
436{
437  int idxAxis = 0;
438  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
439  {
440    if (1 == axisDomainOrder_(i))
441    {
442      elementIndexData_[i].resize(dataNIndex_[i]);
443      elementIndexData_[i] = false;
444      int iIdx = 0, count = 0, localIndex = 0;
445      for (int j = 0; j < dataNIndex_[i]; ++j)
446      {
447        iIdx = getAxisIndex((dataIndex_[indexMap_[i]])(j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
448        if ((iIdx >= nBeginLocal_[indexMap_[i]]) &&
449           (iIdx < nLocal_[indexMap_[i]]) && (axisMasks_[idxAxis](iIdx)))
450        {
451          ++count;
452          elementIndexData_[i](j) = true;
453        }
454      }
455
456      elementLocalIndex_[i].resize(count);
457      elementGlobalIndex_[i].resize(count);
458      elementZoomMask_[i].resize(count);
459      elementZoomMask_[i] = false;
460      count = 0;
461      CArray<bool,1>& tmpIndexElementData = elementIndexData_[i];
462      CArray<bool,1>& tmpZoomMaskElement = elementZoomMask_[i];
463      CArray<int,1>& tmpLocalElementIndex = elementLocalIndex_[i];
464      CArray<size_t,1>& tmpGlobalElementIndex = elementGlobalIndex_[i];
465      for (int j = 0; j < dataNIndex_[i]; ++j)
466      {
467        if (tmpIndexElementData(j))
468        {
469          iIdx = tmpLocalElementIndex(count) = getAxisIndex((dataIndex_[indexMap_[i]])(j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
470          tmpGlobalElementIndex(count) = (infoIndex_[indexMap_[i]])(iIdx);
471          if ((((infoIndex_[indexMap_[i]])(iIdx)) <= nZoomEnd_[indexMap_[i]])
472             && (nZoomBegin_[indexMap_[i]] <= ((infoIndex_[indexMap_[i]])(iIdx))))
473          {
474            tmpZoomMaskElement(count) = true;
475          }
476          ++count;
477        }
478      }
479      ++idxAxis;
480    }
481  }
482}
483
484/*!
485  Create local index of scalar.
486*/
487void CDistributionClient::createLocalScalarDataIndex()
488{
489  int idxAxis = 0;
490  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
491  {
492    if (0 == axisDomainOrder_(i))
493    {
494      elementIndexData_[i].resize(dataNIndex_[i]);
495      elementIndexData_[i] = true;
496      int count = 1;
497
498      elementLocalIndex_[i].resize(count);
499      elementLocalIndex_[i] = 0;
500      elementGlobalIndex_[i].resize(count);
501      elementGlobalIndex_[i] = 0;
502      elementZoomMask_[i].resize(count);
503      elementZoomMask_[i] = true;
504    }
505  }
506}
507
508/*!
509   Create global index on client
510   In order to do the mapping between client-server, each client creates its own
511global index of sending data. This global index is then used to calculate to which server
512the client needs to send it data as well as which part of data belongs to the server.
513So as to make clients and server coherent in order of index, global index is calculated by
514take into account of C-convention, the rightmost dimension varies faster.
515*/
516void CDistributionClient::createGlobalIndexSendToServer()
517{
518  if (isComputed_) return;
519  isComputed_ = true;
520  createLocalDomainDataIndex();
521  createLocalAxisDataIndex();
522  createLocalScalarDataIndex();
523
524  int idxDomain = 0, idxAxis = 0;
525  std::vector<int> eachElementSize(numElement_);
526
527  // Precompute size of the loop
528  for (int i = 0; i < numElement_; ++i)
529  {
530    eachElementSize[i] = elementLocalIndex_[i].numElements();
531  }
532
533  //   Compute size of the global index on client
534  std::vector<StdSize> idxLoop(numElement_,0);
535  std::vector<StdSize> currentIndex(numElement_,0);
536  std::vector<StdSize> currentGlobalIndex(numElement_,0);
537  int innerLoopSize = eachElementSize[0];
538  size_t idx = 0, indexLocalDataOnClientCount = 0, indexSend2ServerCount = 0;
539  size_t ssize = 1;
540  for (int i = 0; i < numElement_; ++i) ssize *= eachElementSize[i];
541  while (idx < ssize)
542  {
543    for (int i = 0; i < numElement_-1; ++i)
544    {
545      if (idxLoop[i] == eachElementSize[i])
546      {
547        idxLoop[i] = 0;
548        ++idxLoop[i+1];
549      }
550    }
551
552    // Find out outer index
553    // Depending the inner-most element is axis or domain,
554    // The outer loop index begins correspondingly at one (1) or zero (0)
555    for (int i = 1; i < numElement_; ++i)
556    {
557      currentIndex[i] = elementLocalIndex_[i](idxLoop[i]);
558    }
559
560    // Inner most index
561    for (int i = 0; i < innerLoopSize; ++i)
562    {
563      int gridMaskIndex = 0;
564      currentIndex[0] = elementLocalIndex_[0](i);
565      for (int k = 0; k < this->numElement_; ++k)
566      {
567        gridMaskIndex += (currentIndex[k])*elementNLocal_[k];
568      }
569
570      if (gridMask_(gridMaskIndex))
571      {
572        ++indexLocalDataOnClientCount;
573        bool isIndexOnServer = true;
574
575        for (int idxElement = 0; idxElement < this->numElement_; ++idxElement)
576        {
577          isIndexOnServer = isIndexOnServer && elementZoomMask_[idxElement](idxLoop[idxElement]);
578        }
579        if (isIndexOnServer) ++indexSend2ServerCount;
580      }
581    }
582    idxLoop[0] += innerLoopSize;
583    idx += innerLoopSize;
584  }
585
586  // Now allocate these arrays
587  localDataIndex_.resize(indexLocalDataOnClientCount);
588  localMaskIndex_.resize(indexSend2ServerCount);
589  globalDataIndex_.rehash(std::ceil(indexLocalDataOnClientCount/globalDataIndex_.max_load_factor())); //globalLocalDataSendToServerMap_.reserve(indexSend2ServerCount);
590  globalLocalDataSendToServerMap_.rehash(std::ceil(indexSend2ServerCount/globalLocalDataSendToServerMap_.max_load_factor())); //globalLocalDataSendToServerMap_.reserve(indexSend2ServerCount);
591
592  // We need to loop with data index
593  idxLoop.assign(numElement_,0);
594  idx = indexLocalDataOnClientCount = indexSend2ServerCount = 0;
595  ssize = 1; for (int i = 0; i < numElement_; ++i) ssize *= dataNIndex_[i];
596  innerLoopSize = dataNIndex_[0];
597  int countLocalData = 0;
598  std::vector<int> correctIndexOfElement(numElement_,0);
599  bool isOuterIndexCorrect = true;
600  while (idx < ssize)
601  {
602    for (int i = 0; i < numElement_-1; ++i)
603    {
604      if (idxLoop[i] == dataNIndex_[i])
605      {
606        idxLoop[i] = 0;
607        correctIndexOfElement[i] = 0;
608        ++idxLoop[i+1];
609        if (isOuterIndexCorrect) ++correctIndexOfElement[i+1];
610      }
611    }
612
613    // Depending the inner-most element axis or domain,
614    // The outer loop index begins correspondingly at one (1) or zero (0)
615    bool isIndexElementDataCorrect = true;
616    for (int i = 1; i < numElement_; ++i)
617    {
618      if (elementIndexData_[i](idxLoop[i]))
619      {
620        currentIndex[i] = elementLocalIndex_[i](correctIndexOfElement[i]);
621        currentGlobalIndex[i] = elementGlobalIndex_[i](correctIndexOfElement[i]);
622        isIndexElementDataCorrect &= true;
623      }
624      else isIndexElementDataCorrect = false;
625    }
626
627    isOuterIndexCorrect = isIndexElementDataCorrect;
628
629    if (isOuterIndexCorrect)
630    {
631      // Inner most index
632      int correctIndexInnerElement = 0;
633      for (int i = 0; i < innerLoopSize; ++i)
634      {
635        bool isCurrentIndexDataCorrect = isOuterIndexCorrect;
636        if (elementIndexData_[0](i))
637        {
638          currentIndex[0] = elementLocalIndex_[0](correctIndexInnerElement);
639          currentGlobalIndex[0] = elementGlobalIndex_[0](correctIndexInnerElement);
640          isCurrentIndexDataCorrect &= true;
641          ++correctIndexInnerElement;
642        }
643        else isCurrentIndexDataCorrect = false;
644
645        if (isCurrentIndexDataCorrect)
646        {
647          int gridMaskIndex = 0;
648          for (int k = 0; k < this->numElement_; ++k)
649          {
650            gridMaskIndex += (currentIndex[k])*elementNLocal_[k];
651          }
652
653          if (gridMask_(gridMaskIndex))
654          {
655            size_t globalIndex = 0;
656            for (int k = 0; k < numElement_; ++k)
657            {
658              globalIndex += (currentGlobalIndex[k])*elementNGlobal_[k];
659            }
660            globalDataIndex_[globalIndex] = indexLocalDataOnClientCount;
661            localDataIndex_[indexLocalDataOnClientCount] = countLocalData;
662            bool isIndexOnServer = true;
663            for (int idxElement = 0; idxElement < this->numElement_; ++idxElement)
664            {
665              isIndexOnServer = isIndexOnServer && elementZoomMask_[idxElement](correctIndexOfElement[idxElement]);
666            }
667
668            if (isIndexOnServer)
669            {
670              globalLocalDataSendToServerMap_[globalIndex] = indexLocalDataOnClientCount;
671              localMaskIndex_[indexSend2ServerCount] = gridMaskIndex;
672              ++indexSend2ServerCount;
673            }
674            ++indexLocalDataOnClientCount;
675          }
676        }
677        ++countLocalData;
678        correctIndexOfElement[0] = correctIndexInnerElement;;
679      }
680    }
681    idxLoop[0] += innerLoopSize;
682    idx += innerLoopSize;
683  }
684}
685
686void CDistributionClient::createGlobalIndex()
687{
688}
689
690/*!
691  Retrieve index i and index j of a domain from its data index
692  Data contains not only true data, which are sent to servers, but also ghost data, which
693very often play a role of border of each local data, so does data index. Because data of a domain
694can be one dimension, or two dimensions, there is a need to convert data index to domain index
695  \param [in] dataIIndex index of i data
696  \param [in] dataJIndex index of j data
697  \param [in] dataIBegin index begin of i data
698  \param [in] dataJBegin index begin of j data
699  \param [in] dataDim dimension of data (1 or 2)
700  \param [in] ni local size ni of domain
701  \param [out] j j index of domain
702  \return i index of domain
703*/
704int CDistributionClient::getDomainIndex(const int& dataIIndex, const int& dataJIndex,
705                                        const int& dataIBegin, const int& dataJBegin,
706                                        const int& dataDim, const int& ni, int& j)
707{
708  int tempI = dataIIndex + dataIBegin,
709      tempJ = (dataJIndex + dataJBegin);
710  int i = (dataDim == 1) ? (tempI) % ni
711                         : (tempI) ;
712  j = (dataDim == 1) ? (tempI) / ni
713                     : (tempJ) ;
714
715  return i;
716}
717
718/*!
719  Retrieve index of an axis from its data index
720  \param [in] dataIndex index of data
721  \param [in] dataBegin index begin of data
722  \param [in] ni local size of axis
723  \return index of domain
724*/
725int CDistributionClient::getAxisIndex(const int& dataIndex, const int& dataBegin, const int& ni)
726{
727   int tempI = dataIndex + dataBegin;
728   return ((tempI)%ni);
729}
730
731/*!
732  Return global local data mapping of client
733*/
734CDistributionClient::GlobalLocalDataMap& CDistributionClient::getGlobalLocalDataSendToServer()
735{
736  if (!isComputed_) createGlobalIndexSendToServer();
737  return globalLocalDataSendToServerMap_;
738}
739
740CDistributionClient::GlobalLocalDataMap& CDistributionClient::getGlobalDataIndexOnClient()
741{
742  if (!isComputed_) createGlobalIndexSendToServer();
743  return globalDataIndex_;
744}
745
746/*!
747  Return local data index of client
748*/
749const std::vector<int>& CDistributionClient::getLocalDataIndexOnClient()
750{
751  if (!isComputed_) createGlobalIndexSendToServer();
752  return localDataIndex_;
753}
754
755/*!
756  Return local mask index of client
757*/
758const std::vector<int>& CDistributionClient::getLocalMaskIndexOnClient()
759{
760  if (!isComputed_) createGlobalIndexSendToServer();
761  return localMaskIndex_;
762}
763
764} // namespace xios
Note: See TracBrowser for help on using the repository browser.