source: XIOS/trunk/src/node/distribution_client.cpp @ 568

Last change on this file since 568 was 567, checked in by mhnguyen, 9 years ago

Implementing a grid formed by only one axis or group of axis

+) Add several new attributes to axis. From now on, each axis can be distributed on client side
+) Modify mask of grid to make it more flexible to different dimension
+) Fix some bugs relating to calculation of local data index on client
+) Clean some redundant codes

Test
+) On Curie, only test_new_features.f90
+) Test cases:

  • Grid composed of: 1 domain and 1 axis, 3 axis, 1 axis
  • Mode: Attached and connected
  • No of client-server: 6-2(Connected), 2 (Attached)

+) All tests passed and results are correct

File size: 19.6 KB
Line 
1/*!
2   \file distribution_client.cpp
3   \author Ha NGUYEN
4   \since 13 Jan 2015
5   \date 09 Feb 2015
6
7   \brief Index distribution on client side.
8 */
9#include "distribution_client.hpp"
10
11namespace xios {
12
13CDistributionClient::CDistributionClient(int rank, int dims, CArray<size_t,1>* globalIndex)
14   : CDistribution(rank, dims, globalIndex),
15   localDataIndex_(0), axisDomainOrder_(),
16   nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_(),nZoomBegin_(), nZoomEnd_(),
17   dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_(), domainMasks_(), axisMasks_(),
18   gridMask_(), localDomainIndex_(), localAxisIndex_(), indexMap_(), indexDomainData_(), indexAxisData_(),
19   isDataDistributed_(true), axisNum_(0), domainNum_(0), localDataIndexSendToServer_(0)
20{
21}
22
23CDistributionClient::CDistributionClient(int rank, CGrid* grid)
24   : CDistribution(rank, 0, 0),
25   localDataIndex_(0), axisDomainOrder_(),
26   nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_(),nZoomBegin_(), nZoomEnd_(),
27   dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_(), domainMasks_(), axisMasks_(),
28   gridMask_(), localDomainIndex_(), localAxisIndex_(), indexMap_(), indexDomainData_(), indexAxisData_(),
29   isDataDistributed_(true), axisNum_(0), domainNum_(0), localDataIndexSendToServer_(0)
30{
31  readDistributionInfo(grid);
32  createGlobalIndex();
33}
34
35CDistributionClient::~CDistributionClient()
36{
37  if (0 != localDataIndex_) delete localDataIndex_;
38  if (0 != localDataIndexSendToServer_) delete localDataIndexSendToServer_;
39}
40
41/*!
42  Read information of a grid to generate distribution.
43  Every grid is composed of several axis or/and domain(s). Their information are processed
44stored and used to calculate index distribution between client and server
45  \param [in] grid Grid to read
46*/
47void CDistributionClient::readDistributionInfo(CGrid* grid)
48{
49  std::vector<CDomain*> domList = grid->getDomains();
50  std::vector<CAxis*> axisList = grid->getAxis();
51  CArray<bool,1> axisDomainOrder = grid->axisDomainOrder;
52
53  std::vector<CDomain*>::iterator itbDom, iteDom, itDom;
54  std::vector<CAxis*>::iterator itbAxis, iteAxis, itAxis;
55
56  itbDom  = itDom  = domList.begin();  iteDom  = domList.end();
57  itbAxis = itAxis = axisList.begin(); iteAxis = axisList.end();
58
59  // First of all, every attribute of domain and axis should be checked
60//  for (;itDom != iteDom; ++itDom) (*itDom)->checkAttributesOnClient();
61//  for (;itAxis != iteAxis; ++itAxis) (*itAxis)->checkAttributesOnClient();
62
63  readDistributionInfo(domList, axisList, axisDomainOrder);
64
65  // Then check mask of grid
66  int gridDim = domList.size()*2 + axisList.size();
67  grid->checkMask();
68  switch (gridDim) {
69    case 1:
70      readGridMaskInfo(grid->mask1);
71      break;
72    case 2:
73      readGridMaskInfo(grid->mask2);
74      break;
75    case 3:
76      readGridMaskInfo(grid->mask3);
77      break;
78    default:
79      break;
80  }
81}
82
83/*!
84  Read information from domain(s) and axis to generate distribution.
85  All information related to domain, e.g ibegin, jbegin, ni, nj, ni_glo, nj_glo
86as well as related to axis, e.g dataNIndex, dataIndex will be stored to compute
87the distribution between clients and servers. Till now, every data structure of domain has been kept
88like before, e.g: data_n_index to make sure a compability, however, it should be changed?
89  \param [in] domList List of domains of grid
90  \param [in] axisList List of axis of grid
91  \param [in] axisDomainOrder order of axis and domain inside a grid. True if domain, false if axis
92//  \param [in] gridMask Mask of grid, for now, keep it 3 dimension, but it needs changing
93*/
94void CDistributionClient::readDistributionInfo(const std::vector<CDomain*>& domList,
95                                               const std::vector<CAxis*>& axisList,
96                                               const CArray<bool,1>& axisDomainOrder)
97{
98  domainNum_ = domList.size();
99  axisNum_   = axisList.size();
100  numElement_ = axisDomainOrder.numElements(); // Number of element, e.x: Axis, Domain
101
102  axisDomainOrder_.resize(numElement_);
103  axisDomainOrder_ = axisDomainOrder;
104
105  // Each domain or axis has its mask, of course
106  domainMasks_.resize(domainNum_);
107  for (int i = 0; i < domainNum_;++i)
108  {
109    domainMasks_[i].resize(domList[i]->mask.extent(0), domList[i]->mask.extent(1));
110    domainMasks_[i] = domList[i]->mask;
111  }
112
113  axisMasks_.resize(axisNum_);
114  for (int i = 0; i < axisNum_; ++i)
115  {
116    axisMasks_[i].resize(axisList[i]->mask.numElements());
117    axisMasks_[i] = axisList[i]->mask;
118  }
119
120  // Because domain and axis can be in any order (axis1, domain1, axis2, axis3, )
121  // their position should be specified. In axisDomainOrder, domain == true, axis == false
122  int idx = 0;
123  indexMap_.resize(numElement_);
124  this->dims_ = numElement_;
125  for (int i = 0; i < numElement_; ++i)
126  {
127    indexMap_[i] = idx;
128    if (true == axisDomainOrder(i))
129    {
130      ++(this->dims_);
131      idx += 2;
132    }
133    else ++idx;
134  }
135
136  // Size of each dimension (local and global)
137  nLocal_.resize(this->dims_);
138  nGlob_.resize(this->dims_);
139  nBeginLocal_.resize(this->dims_,0);
140  nBeginGlobal_.resize(this->dims_,0);
141  nZoomBegin_.resize(this->dims_);
142  nZoomEnd_.resize(this->dims_);
143
144  // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
145  dataNIndex_.resize(numElement_);
146  dataDims_.resize(numElement_);
147  dataBegin_.resize(this->dims_);
148
149  // Data_*_index of each dimension
150  dataIndex_.resize(this->dims_);
151
152  // A trick to determine position of each domain in domainList
153  int domIndex = 0, axisIndex = 0;
154  idx = 0;
155
156  // Update all the vectors above
157  while (idx < numElement_)
158  {
159    bool isDomain = axisDomainOrder(idx);
160
161    // If this is a domain
162    if (isDomain)
163    {
164      // On the j axis
165      nLocal_.at(indexMap_[idx]+1) = domList[domIndex]->nj.getValue();
166      nGlob_.at(indexMap_[idx]+1)  = domList[domIndex]->nj_glo.getValue();
167      nBeginLocal_.at(indexMap_[idx]+1) = 0;
168      nBeginGlobal_.at(indexMap_[idx]+1) = domList[domIndex]->jbegin;
169      nZoomBegin_.at((indexMap_[idx]+1)) = domList[domIndex]->zoom_jbegin;
170      nZoomEnd_.at((indexMap_[idx]+1))   = domList[domIndex]->zoom_jbegin + domList[domIndex]->zoom_nj-1;
171
172      dataBegin_.at(indexMap_[idx]+1) = (2 == domList[domIndex]->data_dim) ? domList[domIndex]->data_jbegin.getValue() : -1;
173      dataIndex_.at(indexMap_[idx]+1).resize(domList[domIndex]->data_j_index.numElements());
174      dataIndex_.at(indexMap_[idx]+1) = domList[domIndex]->data_j_index;
175
176      // On the i axis
177      nLocal_.at(indexMap_[idx]) = domList[domIndex]->ni.getValue();
178      nGlob_.at(indexMap_[idx]) = domList[domIndex]->ni_glo.getValue();
179      nBeginLocal_.at(indexMap_[idx]) = 0;
180      nBeginGlobal_.at(indexMap_[idx]) = domList[domIndex]->ibegin;
181      nZoomBegin_.at((indexMap_[idx])) = domList[domIndex]->zoom_ibegin;
182      nZoomEnd_.at((indexMap_[idx]))   = domList[domIndex]->zoom_ibegin + domList[domIndex]->zoom_ni-1;
183
184      dataBegin_.at(indexMap_[idx]) = domList[domIndex]->data_ibegin.getValue();
185      dataIndex_.at(indexMap_[idx]).resize(domList[domIndex]->data_i_index.numElements());
186      dataIndex_.at(indexMap_[idx]) = domList[domIndex]->data_i_index;
187
188      dataNIndex_.at(idx) = domList[domIndex]->data_n_index.getValue();
189      dataDims_.at(idx) = domList[domIndex]->data_dim.getValue();
190      ++domIndex;
191    }
192    else // So it's an axis
193    {
194      nLocal_.at(indexMap_[idx]) = axisList[axisIndex]->ni.getValue();
195      nGlob_.at(indexMap_[idx]) = axisList[axisIndex]->size.getValue();
196      nBeginLocal_.at(indexMap_[idx]) = 0;
197      nBeginGlobal_.at(indexMap_[idx]) = axisList[axisIndex]->ibegin.getValue();
198      nZoomBegin_.at((indexMap_[idx])) = axisList[axisIndex]->zoom_begin;
199      nZoomEnd_.at((indexMap_[idx])) = axisList[axisIndex]->zoom_begin + axisList[axisIndex]->zoom_size-1;
200
201      dataBegin_.at(indexMap_[idx]) = axisList[axisIndex]->data_begin.getValue();
202      dataIndex_.at(indexMap_[idx]).resize(axisList[axisIndex]->data_index.numElements());
203      dataIndex_.at(indexMap_[idx]) = axisList[axisIndex]->data_index;
204      dataNIndex_.at(idx) = axisList[axisIndex]->data_index.numElements();
205      dataDims_.at(idx) = 1;
206      ++axisIndex;
207    }
208    ++idx;
209  }
210
211  // Grid has only one axis and it is not distributed
212  bool isDataNotDistributed = true;
213  for (int i = 0; i < this->dims_; ++i)
214    isDataNotDistributed &= (nLocal_[i] == nGlob_[i]);
215  isDataDistributed_ = !isDataNotDistributed;
216}
217
218/*!
219  Create local index of domain(s).
220  A domain can have data index which even contains the "ghost" points. Very often, these
221data surround the true data. In order to send correct data to server,
222a client need to know index of the true data.
223*/
224void CDistributionClient::createLocalDomainDataIndex()
225{
226  int numDomain = 0;
227  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
228    if (axisDomainOrder_(i)) ++numDomain;
229
230  localDomainIndex_.resize(numDomain*2);
231  indexDomainData_.resize(numDomain);
232
233  int idxDomain = 0;
234  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
235  {
236    if (axisDomainOrder_(i))
237    {
238      int iIdx, jIdx = 0, count = 0;
239      indexDomainData_[idxDomain].resize(dataNIndex_[i], false);
240      for (int j = 0; j < dataNIndex_[i]; ++j)
241      {
242        iIdx = getDomainIndex(dataIndex_[indexMap_[i]](j), dataIndex_[indexMap_[i]+1](j),
243                              dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
244                              dataDims_[i], nLocal_[indexMap_[i]], jIdx);
245
246        if ((iIdx >= nBeginLocal_[indexMap_[i]]) && (iIdx < nLocal_[indexMap_[i]]) &&
247           (jIdx >= nBeginLocal_[indexMap_[i]+1]) && (jIdx < nLocal_[indexMap_[i]+1]) &&
248           (domainMasks_[idxDomain](iIdx, jIdx)))
249        {
250          (localDomainIndex_[idxDomain]).push_back(iIdx);
251          (localDomainIndex_[idxDomain*2+1]).push_back(jIdx);
252          indexDomainData_[idxDomain][j] = true;
253        }
254      }
255      ++idxDomain;
256    }
257  }
258}
259
260/*!
261  Create local index of axis.
262*/
263void CDistributionClient::createLocalAxisDataIndex()
264{
265  int numAxis = 0;
266  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
267    if (!axisDomainOrder_(i)) ++numAxis;
268
269  localAxisIndex_.resize(numAxis);
270  indexAxisData_.resize(numAxis);
271
272  int idxAxis = 0;
273  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
274  {
275    if (!axisDomainOrder_(i))
276    {
277      int iIdx = 0;
278      indexAxisData_[idxAxis].resize(dataNIndex_[i], false);
279      for (int j = 0; j < dataNIndex_[i]; ++j)
280      {
281        iIdx = getAxisIndex(dataIndex_[indexMap_[i]](j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
282        if ((iIdx >= nBeginLocal_[indexMap_[i]]) &&
283           (iIdx < nLocal_[indexMap_[i]]) && (axisMasks_[idxAxis](iIdx)))
284        {
285          localAxisIndex_[idxAxis].push_back(iIdx);
286          indexAxisData_[idxAxis][j] = true;
287        }
288      }
289      ++idxAxis;
290    }
291  }
292}
293
294/*!
295   Create global index on client
296   In order to do the mapping between client-server, each client creates its own
297global index of sending data. This global index is then used to calculate to which server
298the client needs to send it data as well as which part of data belongs to the server.
299So as to make clients and server coherent in order of index, global index is calculated by
300take into account of C-convention, the rightmost dimension varies faster.
301*/
302void CDistributionClient::createGlobalIndex()
303{
304  createLocalDomainDataIndex();
305  createLocalAxisDataIndex();
306
307  int idxDomain = 0, idxAxis = 0;
308  std::vector<int> eachElementSize(numElement_);
309
310  // Precompute size of the loop
311  for (int i = 0; i < numElement_; ++i)
312  {
313    if(axisDomainOrder_(i))
314    {
315      eachElementSize[i] = localDomainIndex_[idxDomain].size();
316      idxDomain += 2;
317    }
318    else
319    {
320      eachElementSize[i] = localAxisIndex_[idxAxis].size();
321      ++idxAxis;
322    }
323  }
324
325  //   Compute size of the global index on client
326  std::vector<int> idxLoop(numElement_,0);
327  std::vector<int> currentIndex(this->dims_);
328  int innerLoopSize = eachElementSize[0];
329  size_t idx = 0, indexLocalDataOnClientCount = 0, indexSend2ServerCount = 0;
330  size_t ssize = 1;
331  for (int i = 0; i < numElement_; ++i) ssize *= eachElementSize[i];
332  while (idx < ssize)
333  {
334    for (int i = 0; i < numElement_-1; ++i)
335    {
336      if (idxLoop[i] == eachElementSize[i])
337      {
338        idxLoop[i] = 0;
339        ++idxLoop[i+1];
340      }
341    }
342
343    // Find out outer index
344    // Depending the inner-most element is axis or domain,
345    // The outer loop index begins correspondingly at one (1) or zero (0)
346    idxDomain = idxAxis = 0;
347    if (axisDomainOrder_(0)) ++idxDomain;
348    else ++idxAxis;
349    for (int i = 1; i < numElement_; ++i)
350    {
351      if (axisDomainOrder_(i))
352      {
353        currentIndex[indexMap_[i]]   = localDomainIndex_[idxDomain][idxLoop[i]];
354        currentIndex[indexMap_[i]+1] = localDomainIndex_[idxDomain+1][idxLoop[i]];
355        idxDomain += 2;
356      }
357      else
358      {
359        currentIndex[indexMap_[i]]   = localAxisIndex_[idxAxis][idxLoop[i]];
360        ++idxAxis;
361      }
362    }
363
364    int maskIndex = currentIndex[0];
365    for (int j = 0; j < this->dims_; ++j)
366
367    // Inner most index
368    idxDomain = idxAxis = 0;
369    for (int i = 0; i < innerLoopSize; ++i)
370    {
371      if (axisDomainOrder_(0))
372      {
373        currentIndex[0] = localDomainIndex_[idxDomain][i];
374        currentIndex[1] = localDomainIndex_[idxDomain+1][i];
375      }
376      else currentIndex[0]   = localAxisIndex_[idxAxis][i];
377
378      int gridMaskIndex = currentIndex[0];
379      int mulDimMask = 1;
380      for (int k = 1; k < this->dims_; ++k)
381      {
382        mulDimMask *= nLocal_[k-1];
383        gridMaskIndex += (currentIndex[k])*mulDimMask;
384      }
385
386      if (gridMask_(gridMaskIndex)) //(gridMask_(currentIndex[0], currentIndex[1], currentIndex[2]))
387      {
388        ++indexLocalDataOnClientCount;
389        bool isIndexOnServer = true;
390        for (int j = 0; j < this->dims_; ++j)
391          isIndexOnServer = isIndexOnServer && ((currentIndex[j]+nBeginGlobal_[j]) <= nZoomEnd_[j])
392                                            && (nZoomBegin_[j] <= (currentIndex[j]+nBeginGlobal_[j]));
393        if (isIndexOnServer) ++indexSend2ServerCount;
394      }
395
396    }
397    idxLoop[0] += innerLoopSize;
398    idx += innerLoopSize;
399  }
400
401
402  // Now allocate these arrays
403  this->globalIndex_ = new CArray<size_t,1>(indexSend2ServerCount);
404  localDataIndex_ = new CArray<int,1>(indexLocalDataOnClientCount);
405  localDataIndexSendToServer_ = new CArray<int,1>(indexSend2ServerCount);
406
407  // We need to loop with data index
408  idxLoop.assign(numElement_,0);
409  idx = indexLocalDataOnClientCount = indexSend2ServerCount = 0;
410  ssize = 1; for (int i = 0; i < numElement_; ++i) ssize *= dataNIndex_[i];
411  innerLoopSize = dataNIndex_[0];
412  int countLocalData = 0;
413  std::vector<int> correctOuterIndex(numElement_,0);
414  while (idx < ssize)
415  {
416    for (int i = 0; i < numElement_-1; ++i)
417    {
418      if (idxLoop[i] == dataNIndex_[i])
419      {
420        idxLoop[i] = 0;
421        correctOuterIndex[i] = 0;
422        ++idxLoop[i+1];
423        ++correctOuterIndex[i+1];
424      }
425    }
426
427    // Depending the inner-most element axis or domain,
428    // The outer loop index begins correspondingly at one (1) or zero (0)
429    idxDomain = idxAxis = 0;
430    if (axisDomainOrder_(0)) ++idxDomain;
431    else ++idxAxis;
432    bool isIndexDomainDataCorrect = true;
433    bool isIndexAxisDataCorrect = true;
434
435    for (int i = 1; i < numElement_; ++i)
436    {
437      if (axisDomainOrder_(i))
438      {
439        if (indexDomainData_[idxDomain][idxLoop[i]])
440        {
441          currentIndex[indexMap_[i]]   = localDomainIndex_[idxDomain][correctOuterIndex[i]];
442          currentIndex[indexMap_[i]+1] = localDomainIndex_[idxDomain*2+1][correctOuterIndex[i]];
443        }
444        else isIndexDomainDataCorrect = false;
445        ++idxDomain;
446      }
447      else
448      {
449        if (indexAxisData_[idxAxis][idxLoop[i]])
450        {
451          currentIndex[indexMap_[i]]   = localAxisIndex_[idxAxis][correctOuterIndex[i]];
452        }
453        else isIndexAxisDataCorrect = false;
454        ++idxAxis;
455      }
456    }
457
458    // Inner most index
459    idxDomain = idxAxis = 0;
460    int correctIndexDomain = 0, correctIndexAxis = 0;
461    for (int i = 0; i < innerLoopSize; ++i)
462    {
463      if (axisDomainOrder_(0))
464      {
465        if (indexDomainData_[idxDomain][i])
466        {
467          currentIndex[0] = localDomainIndex_[idxDomain][correctIndexDomain];
468          currentIndex[1] = localDomainIndex_[idxDomain+1][correctIndexDomain];
469          isIndexDomainDataCorrect = true;
470          ++correctIndexDomain;
471        }
472        else isIndexDomainDataCorrect = false;
473      }
474      else
475      {
476        if (indexAxisData_[idxAxis][i])
477        {
478          currentIndex[0] = localAxisIndex_[idxAxis][correctIndexAxis];
479          isIndexAxisDataCorrect = true;
480          ++correctIndexAxis;
481        }
482        else isIndexAxisDataCorrect = false;
483      }
484
485      int gridMaskIndex = currentIndex[0];
486      int mulDimMask = 1;
487      for (int k = 1; k < this->dims_; ++k)
488      {
489        mulDimMask *= nLocal_[k-1];
490        gridMaskIndex += (currentIndex[k])*mulDimMask;
491      }
492
493      if (isIndexDomainDataCorrect &&
494          isIndexAxisDataCorrect &&
495          gridMask_(gridMaskIndex))
496      {
497        (*localDataIndex_)(indexLocalDataOnClientCount) = countLocalData;
498
499        bool isIndexOnServer = true;
500        for (int j = 0; j < this->dims_; ++j)
501          isIndexOnServer = isIndexOnServer &&
502                            ((currentIndex[j]+nBeginGlobal_[j]) <= nZoomEnd_[j]) &&
503                            (nZoomBegin_[j] <= (currentIndex[j]+nBeginGlobal_[j]));
504        if (isIndexOnServer)
505        {
506          size_t globalIndex = currentIndex[0] + nBeginGlobal_[0];
507          size_t mulDim = 1;
508          for (int k = 1; k < this->dims_; ++k)
509          {
510            mulDim *= nGlob_[k-1];
511            globalIndex += (currentIndex[k] + nBeginGlobal_[k])*mulDim;
512          }
513          (*this->globalIndex_)(indexSend2ServerCount) = globalIndex;
514          (*localDataIndexSendToServer_)(indexSend2ServerCount) = indexLocalDataOnClientCount;
515          ++indexSend2ServerCount;
516        }
517        ++indexLocalDataOnClientCount;
518      }
519      ++countLocalData;
520    }
521    idxLoop[0] += innerLoopSize;
522    idx += innerLoopSize;
523  }
524}
525
526/*!
527  Retrieve index i and index j of a domain from its data index
528  Data contains not only true data, which are sent to servers, but also ghost data, which
529very often play a role of border of each local data, so does data index. Because data of a domain
530can be one dimension, or two dimensions, there is a need to convert data index to domain index
531  \param [in] dataIIndex index of i data
532  \param [in] dataJIndex index of j data
533  \param [in] dataIBegin index begin of i data
534  \param [in] dataJBegin index begin of j data
535  \param [in] dataDim dimension of data (1 or 2)
536  \param [in] ni local size ni of domain
537  \param [out] j j index of domain
538  \return i index of domain
539*/
540int CDistributionClient::getDomainIndex(const int& dataIIndex, const int& dataJIndex,
541                                        const int& dataIBegin, const int& dataJBegin,
542                                        const int& dataDim, const int& ni, int& j)
543{
544  int tempI = dataIIndex + dataIBegin,
545      tempJ = (1 == dataDim) ? -1
546                             : (dataJIndex + dataJBegin);
547  int i = (dataDim == 1) ? (tempI - 1) % ni
548                     : (tempI - 1) ;
549  j = (dataDim == 1) ? (tempI - 1) / ni
550                     : (tempJ - 1) ;
551
552  return i;
553}
554
555/*!
556  Retrieve index of an axis from its data index
557  \param [in] dataIndex index of data
558  \param [in] dataBegin index begin of data
559  \param [in] ni local size of axis
560  \return index of domain
561*/
562int CDistributionClient::getAxisIndex(const int& dataIndex, const int& dataBegin, const int& ni)
563{
564   int tempI = dataIndex + dataBegin;
565   return ((tempI-1)%ni);
566}
567
568/*!
569  Return local data index of client
570*/
571const CArray<int,1>& CDistributionClient::getLocalDataIndexOnClient() const
572{
573  return (*localDataIndex_);
574}
575
576const CArray<int,1>& CDistributionClient::getLocalDataIndexSendToServerOnClient() const
577{
578  return (*localDataIndexSendToServer_);
579}
580
581} // namespace xios
Note: See TracBrowser for help on using the repository browser.