source: XIOS/trunk/src/distribution_client.cpp @ 2250

Last change on this file since 2250 was 2131, checked in by oabramkina, 3 years ago

Merging branch dev_oa with tiling into trunk

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