source: XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp @ 1263

Last change on this file since 1263 was 1263, checked in by oabramkina, 7 years ago

Modifications allowing to avoid recalculation of the grid distribution if receivers are of the same size.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 87.4 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20
21namespace xios {
22
23   /// ////////////////////// Dfinitions ////////////////////// ///
24
25   CGrid::CGrid(void)
26      : CObjectTemplate<CGrid>(), CGridAttributes()
27      , isChecked(false), isDomainAxisChecked(false)
28      , vDomainGroup_(), domList_(), isDomListSet(false)
29      , vAxisGroup_(), axisList_(), isAxisListSet(false)
30      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
31      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
32      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
33      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
34      , transformations_(0), isTransformed_(false)
35      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
36      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
37      , computedWrittenIndex_(false)
38   {
39     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
40     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
41     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
42   }
43
44   CGrid::CGrid(const StdString& id)
45      : CObjectTemplate<CGrid>(id), CGridAttributes()
46      , isChecked(false), isDomainAxisChecked(false)
47      , vDomainGroup_(), domList_(), isDomListSet(false)
48      , vAxisGroup_(), axisList_(), isAxisListSet(false)
49      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
50      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
51      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
52      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
53      , transformations_(0), isTransformed_(false)
54      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
55      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
56      , computedWrittenIndex_(false)
57   {
58     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
59     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
60     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
61   }
62
63   CGrid::~CGrid(void)
64   {
65    if (0 != clientDistribution_) delete clientDistribution_;
66    if (0 != serverDistribution_) delete serverDistribution_;
67    if (0 != clientServerMap_) delete clientServerMap_;
68    if (0 != transformations_) delete transformations_;
69   }
70
71   ///---------------------------------------------------------------
72
73   StdString CGrid::GetName(void)    { return StdString("grid"); }
74   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
75   ENodeType CGrid::GetType(void)    { return eGrid; }
76
77
78   StdSize CGrid::getDimension(void)
79   {
80      return getGlobalDimension().size();
81   }
82
83   //---------------------------------------------------------------
84
85   StdSize CGrid::getDataSize(void) const
86   {
87     StdSize retvalue = 1;
88     if (!isScalarGrid())
89     {
90       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
91       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];       
92     }
93     return retvalue;
94   }
95
96   /*!
97    * Compute the minimum buffer size required to send the attributes to the server(s).
98    *
99    * \return A map associating the server rank with its minimum buffer size.
100    * TODO: Refactor code
101    */
102   std::map<int, StdSize> CGrid::getAttributesBufferSize(CContextClient* client)
103   {
104     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
105
106     // The grid indexes require a similar size as the actual data
107     std::map<int, StdSize> dataSizes = getDataBufferSize(client);
108     // for (size_t i = 0; i < dataSizes.size(); ++i)
109     // {
110       std::map<int, StdSize>::iterator it, itE = dataSizes.end();
111       for (it = dataSizes.begin(); it != itE; ++it)
112       {
113         it->second += 2 * sizeof(bool);
114         if (it->second > attributesSizes[it->first])
115           attributesSizes[it->first] = it->second;
116       }
117     // }
118
119     
120     // Account for the axis attributes
121     std::vector<CAxis*> axisList = getAxis();
122     for (size_t i = 0; i < axisList.size(); ++i)
123     {
124       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client);       
125       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
126       {
127         if (it->second > attributesSizes[it->first])
128           attributesSizes[it->first] = it->second;
129       }
130     }
131
132     // Account for the domain attributes
133     std::vector<CDomain*> domList = getDomains();
134     for (size_t i = 0; i < domList.size(); ++i)
135     {
136       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize(client);
137       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
138       {
139         if (it->second > attributesSizes[it->first])
140           attributesSizes[it->first] = it->second;
141       }
142     }
143
144     return attributesSizes;
145  }
146
147   /*!
148    * Compute the minimum buffer size required to send the data.
149    * \param client contextClient used to determine the size of connected receivers
150    * \param id the id used to tag the data
151    * \return A map associating the sender rank with its minimum buffer size.
152    */
153   std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/)
154   {     
155     // The record index is sometimes sent along with the data but we always
156     // include it in the size calculation for the sake of simplicity
157     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() 
158                                                       + 2 * sizeof(size_t) 
159                                                       + sizeof(size_t);
160     // CContext* context = CContext::getCurrent();
161     // int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
162     // std::vector<std::map<int, StdSize> > dataSizes(nbSrvPools);
163     // for (int p = 0; p < nbSrvPools; ++p)
164     // {
165     //   std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[client].end();
166     //   for (size_t k = 0; k < connectedServerRank_[p].size(); ++k)
167     //   {
168     //     int rank = connectedServerRank_[p][k];
169     //     std::map<int, size_t>::const_iterator it = connectedDataSize_[client].find(rank);
170     //     size_t count = (it != itEnd) ? it->second : 0;
171
172     //     dataSizes[p].insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
173     //   }
174       
175     // }
176
177     std::map<int, StdSize> dataSizes;
178     int receiverSize = client->serverSize;
179     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[receiverSize].end();
180     for (size_t k = 0; k < connectedServerRank_[receiverSize].size(); ++k)
181     {
182       int rank = connectedServerRank_[receiverSize][k];
183       std::map<int, size_t>::const_iterator it = connectedDataSize_[receiverSize].find(rank);
184       size_t count = (it != itEnd) ? it->second : 0;
185
186       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
187     }
188
189     return dataSizes;
190   }
191
192   size_t CGrid::getGlobalWrittenSize(void)
193   {
194         std::vector<CDomain*> domainP = this->getDomains();
195     std::vector<CAxis*> axisP = this->getAxis();
196     
197     size_t globalGridSize=1 ;
198     for (std::vector<CDomain*>::iterator it=domainP.begin(); it!=domainP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
199     for (std::vector<CAxis*>::iterator it=axisP.begin(); it!=axisP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
200     return globalGridSize ;
201   }
202   
203   
204   void CGrid::checkAttributesAfterTransformation()
205   {
206      setAxisList();
207      std::vector<CAxis*> axisListP = this->getAxis();
208      if (!axisListP.empty())
209      {
210        int idx = 0;
211        axisPositionInGrid_.resize(0);
212        for (int i = 0; i < axis_domain_order.numElements(); ++i)
213        {
214          int elementDimension = axis_domain_order(i);
215          if (1 == elementDimension)
216          {
217            axisPositionInGrid_.push_back(idx);
218            ++idx;
219          }
220          else if (2 == elementDimension) idx += 2;
221        }
222
223        for (int i = 0; i < axisListP.size(); ++i)
224        {
225          axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(),axisPositionInGrid_[i]);
226        }
227      }
228
229      setDomainList();
230      std::vector<CDomain*> domListP = this->getDomains();
231      if (!domListP.empty())
232      {
233        for (int i = 0; i < domListP.size(); ++i)
234        {
235          domListP[i]->checkAttributesOnClientAfterTransformation();
236        }
237      }
238   }
239
240   //---------------------------------------------------------------
241
242   /*!
243    * Test whether the data defined on the grid can be outputted in a compressed way.
244    *
245    * \return true if and only if a mask was defined for this grid
246    */
247   bool CGrid::isCompressible(void) const
248   {
249      return isCompressible_;
250   }
251
252   //---------------------------------------------------------------
253
254   void CGrid::addRelFileCompressed(const StdString& filename)
255   {
256      this->relFilesCompressed.insert(filename);
257   }
258
259   bool CGrid::isWrittenCompressed(const StdString& filename) const
260   {
261      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
262   }
263
264   //---------------------------------------------------------------
265   /*
266     Find all reference of grid's components and inherite attributes if necessary
267   */
268   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
269   {
270     if (this->isDomainAxisChecked) return;
271
272     this->solveScalarRef(areAttributesChecked);
273     this->solveAxisRef(areAttributesChecked);
274     this->solveDomainRef(areAttributesChecked);     
275     this->isDomainAxisChecked = areAttributesChecked;
276   }
277
278   /*
279     Go up hierachy reference and fill in the base reference with attributes of the children
280     This function should be only used after reading component's attributes from file
281   */
282   void CGrid::solveDomainAxisBaseRef()
283   {
284     if (this->hasDomainAxisBaseRef_) return;
285     // Account for the scalar attributes
286     std::vector<CScalar*> scalarList = getScalars();
287     for (size_t i = 0; i < scalarList.size(); ++i)
288     {
289       scalarList[i]->setAttributesReference();
290     }
291
292     // Account for the axis attributes
293     std::vector<CAxis*> axisList = getAxis();
294     for (size_t i = 0; i < axisList.size(); ++i)
295     {
296       axisList[i]->setAttributesReference();
297     }
298
299     // Account for the domain attributes
300     std::vector<CDomain*> domList = getDomains();
301     for (size_t i = 0; i < domList.size(); ++i)
302     {
303       domList[i]->setAttributesReference();
304     }
305
306     this->hasDomainAxisBaseRef_ = true;
307   }
308
309   void CGrid::checkEligibilityForCompressedOutput()
310   {
311     // We don't check if the mask is valid here, just if a mask has been defined at this point.
312     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
313   }
314
315   void CGrid::checkMaskIndex(bool doSendingIndex)
316   {
317     CContext* context = CContext::getCurrent();
318     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;   
319     nbSrvPools = 1; 
320     for (int p = 0; p < nbSrvPools; ++p)
321     {   
322       if (context->hasClient && this->isChecked && doSendingIndex && !isIndexSent) 
323       { 
324         if (isScalarGrid())
325           sendIndexScalarGrid();
326         else
327           sendIndex();
328         this->isIndexSent = true; 
329       }
330
331       // Not sure about this
332       //if (!(this->hasTransform() && !this->isTransformed()))
333       // this->isChecked = true;
334       //return;
335     }
336   
337     if (this->isChecked) return;
338     this->checkAttributesAfterTransformation();
339
340     // TODO: Transfer grid attributes
341     //if (!context->hasClient && context->hasServer) this->createMask();
342     this->computeIndex();
343
344     if (!(this->hasTransform() && !this->isTransformed()))
345      this->isChecked = true;
346
347     if (!(this->hasTransform() && (!this->isGenerated())))
348      this->isChecked = true;
349   }
350
351   /*
352     Create mask of grid from mask of its components
353   */
354   void CGrid::createMask(void)
355   {
356      using namespace std;
357      std::vector<CDomain*> domainP = this->getDomains();
358      std::vector<CAxis*> axisP = this->getAxis();
359      int dim = domainP.size() * 2 + axisP.size();
360
361      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
362      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
363      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
364      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
365
366      switch (dim) {
367        case 1:
368          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
369          break;
370        case 2:
371          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
372          break;
373        case 3:
374          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
375          break;
376        case 4:
377          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true);
378          break;
379        case 5:
380          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true);
381          break;
382        case 6:
383          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true);
384          break;
385        case 7:
386          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true);
387          break;
388        default:
389          break;
390      }
391   }
392
393   /*
394     Check validity of grid's mask by using the masks of its components
395   */
396   void CGrid::checkMask(void)
397   {
398      using namespace std;
399      std::vector<CDomain*> domainP = this->getDomains();
400      std::vector<CAxis*> axisP = this->getAxis();
401      int dim = domainP.size() * 2 + axisP.size();
402
403      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
404      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
405      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
406      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
407
408      switch (dim) {
409        case 1:
410          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
411          break;
412        case 2:
413          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
414          break;
415        case 3:
416          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
417          break;
418        case 4:
419          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order);
420          break;
421        case 5:
422          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order);
423          break;
424        case 6:
425          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order);
426          break;
427        case 7:
428          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order);
429          break;
430        default:
431          break;
432      }
433   }
434
435   /*
436     Modify value of mask in a certain index
437     This function can be used to correct the mask of grid after being constructed with createMask
438     \param [in] indexToModify
439     \param [in] modifyValue
440   */
441   void CGrid::modifyMask(const CArray<int,1>& indexToModify, bool modifyValue)
442   {
443      using namespace std;
444      std::vector<CDomain*> domainP = this->getDomains();
445      std::vector<CAxis*> axisP = this->getAxis();
446      int dim = domainP.size() * 2 + axisP.size();
447
448      switch (dim) {
449        case 0:
450          modifyGridMask(mask_0d, indexToModify, modifyValue);
451          break;
452        case 1:
453          modifyGridMask(mask_1d, indexToModify, modifyValue);
454          break;
455        case 2:
456          modifyGridMask(mask_2d, indexToModify, modifyValue);
457          break;
458        case 3:
459          modifyGridMask(mask_3d, indexToModify, modifyValue);
460          break;
461        case 4:
462          modifyGridMask(mask_4d, indexToModify, modifyValue);
463          break;
464        case 5:
465          modifyGridMask(mask_5d, indexToModify, modifyValue);
466          break;
467        case 6:
468          modifyGridMask(mask_6d, indexToModify, modifyValue);
469          break;
470        case 7:
471          modifyGridMask(mask_7d, indexToModify, modifyValue);
472          break;
473        default:
474          break;
475      }
476   }
477
478   /*
479     Change the mask size. This function is used on reconstructing mask in server side
480     \param [in] newDimensionSize
481     \param [in] newValue
482   */
483   void CGrid::modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue)
484   {     
485      std::vector<CDomain*> domainP = this->getDomains();
486      std::vector<CAxis*> axisP = this->getAxis();           
487      int dim = domainP.size() * 2 + axisP.size();
488
489      switch (dim) {
490        case 0:
491          modifyGridMaskSize(mask_0d, newDimensionSize, newValue);
492          break;
493        case 1:
494          modifyGridMaskSize(mask_1d, newDimensionSize, newValue);
495          break;
496        case 2:
497          modifyGridMaskSize(mask_2d, newDimensionSize, newValue);
498          break;
499        case 3:
500          modifyGridMaskSize(mask_3d, newDimensionSize, newValue);
501          break;
502        case 4:
503          modifyGridMaskSize(mask_4d, newDimensionSize, newValue);
504          break;
505        case 5:
506          modifyGridMaskSize(mask_5d, newDimensionSize, newValue);
507          break;
508        case 6:
509          modifyGridMaskSize(mask_6d, newDimensionSize, newValue);
510          break;
511        case 7:
512          modifyGridMaskSize(mask_7d, newDimensionSize, newValue);
513          break;
514        default:
515          break;
516      }
517   }
518
519   //---------------------------------------------------------------
520
521   void CGrid::solveDomainRef(bool sendAtt)
522   {
523      setDomainList();
524      std::vector<CDomain*> domListP = this->getDomains();
525      if (!domListP.empty())
526      {
527        for (int i = 0; i < domListP.size(); ++i)
528        {
529          if (sendAtt) domListP[i]->sendCheckedAttributes();
530          else domListP[i]->checkAttributesOnClient();
531        }
532      }
533   }
534
535   //---------------------------------------------------------------
536
537   void CGrid::solveAxisRef(bool sendAtt)
538   {
539      setAxisList();
540      std::vector<CAxis*> axisListP = this->getAxis();
541      if (!axisListP.empty())
542      {
543        int idx = 0;
544        axisPositionInGrid_.resize(0);
545        for (int i = 0; i < axis_domain_order.numElements(); ++i)
546        {
547          int elementDimension = axis_domain_order(i);
548          if (1 == elementDimension)
549          {
550            axisPositionInGrid_.push_back(idx);
551            ++idx;
552          }
553          else if (2 == elementDimension) idx += 2;
554        }
555
556        for (int i = 0; i < axisListP.size(); ++i)
557        {
558          if (sendAtt)
559            axisListP[i]->sendCheckedAttributes(getGlobalDimension(),axisPositionInGrid_[i]);
560          else
561            axisListP[i]->checkAttributesOnClient();
562        }
563      }
564   }
565
566   //---------------------------------------------------------------
567
568   void CGrid::solveScalarRef(bool sendAtt)
569   {
570      setScalarList();
571      std::vector<CScalar*> scalarListP = this->getScalars();
572      if (!scalarListP.empty())
573      {
574        for (int i = 0; i < scalarListP.size(); ++i)
575        {
576          /*Nothing to do for now */
577//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
578//          else scalarListP[i]->checkAttributesOnClient();
579        }
580      }
581   }
582
583   /*!
584      Compute the index to for write data into a file
585   */
586   void CGrid::computeWrittenIndex()
587   {     
588      if (computedWrittenIndex_) return;
589      computedWrittenIndex_ = true;
590
591      if (isScalarGrid())
592      {
593        size_t nbWritten = 1;
594        int writtenIndex = 0;
595
596        localIndexToWriteOnClient.resize(nbWritten); 
597        localIndexToWriteOnServer.resize(nbWritten);
598        localIndexToWriteOnServer(0) = writtenIndex;
599        localIndexToWriteOnClient(0) = writtenIndex;
600       
601        return;
602      }
603
604      size_t nbWritten = 0, indGlo;
605      CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
606      CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(),
607                                                              ite = globalDataIndex.end(), it;   
608      const CDistributionServer::GlobalLocalMap& globalLocalIndex = serverDistribution_->getGlobalLocalIndex();                                                             
609      CDistributionServer::GlobalLocalMap::const_iterator itSrvb = globalLocalIndex.begin(),
610                                                          itSrve = globalLocalIndex.end(), itSrv;
611      for (it = itb; it != ite; ++it)
612      {
613        indGlo = it->first;
614        if (globalLocalIndex.end() != globalLocalIndex.find(indGlo)) ++nbWritten;               
615      }
616
617      localIndexToWriteOnClient.resize(nbWritten); 
618      localIndexToWriteOnServer.resize(nbWritten);
619     
620      {
621        numberWrittenIndexes_ = nbWritten;
622        if (isDataDistributed_)
623        {
624          CContextServer* server = CContext::getCurrent()->server;     
625          MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
626          MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
627          offsetWrittenIndexes_ -= numberWrittenIndexes_;
628        }
629        else
630          totalNumberWrittenIndexes_ = numberWrittenIndexes_;
631      }
632
633      nbWritten = 0; 
634      for (it = itb; it != ite; ++it)
635      {
636        indGlo = it->first;
637        itSrv = globalLocalIndex.find(indGlo);
638        if (itSrve != itSrv)
639        {
640          localIndexToWriteOnServer(nbWritten) = itSrv->second;
641          localIndexToWriteOnClient(nbWritten) = it->second;
642          ++nbWritten;               
643        } 
644      }
645
646   }
647
648   //---------------------------------------------------------------
649
650   /*
651     Compute the global index and its local index on taking account of mask, data index.
652     These global index then will be used to compute the connection of this client to other clients in the different group
653     (via function computeConnectedClient)
654     These global index also corresponding to data sent to other clients (if any)
655   */
656   void CGrid::computeClientIndex()
657   {
658     CContext* context = CContext::getCurrent();
659
660     CContextClient* client = context->client;  // Here it's not important which contextClient to recuperate
661     int rank = client->clientRank;
662
663     clientDistribution_ = new CDistributionClient(rank, this);
664     // Get local data index on client
665     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
666     int nbStoreIndex = storeIndex_client.numElements();
667     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
668
669     if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed();
670     else
671     {
672        // Mapping global index received from clients to the storeIndex_client
673        CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
674        CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
675        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
676                                               ite = outGlobalIndexFromClient.end(), it;
677
678        for (it = itb; it != ite; ++it)
679        {
680          int rank = it->first;
681          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
682          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
683          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
684          size_t nbIndex = 0;
685
686          // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
687          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
688          {
689            if (itGloe != globalDataIndex.find(globalIndex(idx)))
690            {
691              ++nbIndex;
692            }
693          }
694
695          if (doGridHaveDataDistributed(client) && (nbIndex != localIndex.numElements()))
696               ERROR("void CGrid::computeClientIndex()",
697                  << "Number of local index on client is different from number of received global index"
698                  << "Rank of sent client " << rank <<"."
699                  << "Number of local index " << nbIndex << ". "
700                  << "Number of received global index " << localIndex.numElements() << ".");
701
702          nbIndex = 0;
703          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
704          {
705            if (itGloe != globalDataIndex.find(globalIndex(idx)))
706            {
707              localIndex(idx) = globalDataIndex[globalIndex(idx)];
708            }
709          }
710        }
711      }
712   }
713
714   /*!
715     Compute connected receivers and indexes to be sent to these receivers.
716   */
717   void CGrid::computeConnectedClients()
718   {
719     CContext* context = CContext::getCurrent();
720     int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size();
721     connectedServerRank_.clear();
722     connectedDataSize_.clear();
723     globalIndexOnServer_.clear();
724     nbSenders.clear();
725
726     for (int p = 0; p < nbSrvPools; ++p)
727     {
728       CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p];
729       int receiverSize = client->serverSize;
730//       connectedServerRank_[client].clear();
731
732       if (connectedServerRank_.find(receiverSize) == connectedServerRank_.end())
733       {
734        if (!doGridHaveDataDistributed(client))
735         {
736            if (client->isServerLeader())
737            {
738              size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
739              const std::list<int>& ranks = client->getRanksServerLeader();
740              for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
741              {
742                connectedServerRank_[receiverSize].push_back(*itRank);
743                connectedDataSize_[receiverSize][*itRank] = ssize;
744              }
745            }
746            return;
747         }
748
749         // Compute mapping between client and server
750         std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
751         CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
752         std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
753                                                                                                    client->clientRank,
754                                                                                                    client->clientSize,
755                                                                                                    axis_domain_order,
756                                                                                                    getDistributedDimension());
757
758         // Even if servers have no index, they must received something from client
759         // We only use several client to send "empty" message to these servers
760         std::list<int> serverZeroIndexLeader;
761         std::list<int> serverZeroIndexNotLeader;
762         CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
763         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
764           *it = serverZeroIndex[*it];
765
766         if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end())
767           computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]);
768
769         const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
770         CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
771         CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
772         itbGlobalMap = globalIndexOnServer_[receiverSize].begin();
773         iteGlobalMap = globalIndexOnServer_[receiverSize].end();
774
775         for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
776         {
777           int serverRank = itGlobalMap->first;
778           int indexSize = itGlobalMap->second.size();
779           const std::vector<size_t>& indexVec = itGlobalMap->second;
780           for (int idx = 0; idx < indexSize; ++idx)
781           {
782              itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
783              if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
784              {
785                if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank))
786                  connectedDataSize_[receiverSize][serverRank] = 1;
787                else
788                  ++connectedDataSize_[receiverSize][serverRank];
789              }
790           }
791         }
792
793         // Connected servers which really have index
794         for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
795           connectedServerRank_[receiverSize].push_back(itGlobalMap->first);
796         }
797
798         // Connected servers which have no index at all
799         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
800           connectedServerRank_[receiverSize].push_back(*it);
801
802         // Even if a client has no index, it must connect to at least one server and
803         // send an "empty" data to this server
804         if (connectedServerRank_[receiverSize].empty())
805          connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);
806
807         nbSenders[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);
808       }
809     }
810   }
811
812   /*!
813     Compute the global index of grid to send to server as well as the connected server of the current client.
814     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
815     their global index. We can have a map of global index of grid and local index that each client holds
816     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
817     of the current client.
818   */
819   void CGrid::computeIndex(void)
820   {
821     CContext* context = CContext::getCurrent();
822     if (isScalarGrid())
823     {
824       computeClientIndexScalarGrid();
825       if (context->hasClient)
826       {
827         computeConnectedClientsScalarGrid();
828       }
829     }
830     else
831     {
832       computeClientIndex();
833       if (context->hasClient)
834       {
835         computeConnectedClients();
836       }
837     }
838   }
839
840   /*!
841      Compute the global of (client) grid to send to server with the global index of each element of grid
842      Each element of grid has its own global index associated to a groups of server. We only search for the global index of each element whose
843      server is the same, then calculate the global index of grid. This way can reduce so much the time for executing DHT, which only needs to run
844      on each element whose size is much smaller than one of whole grid.
845      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
846      \param [in] client contextClient
847      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
848   */
849   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
850                                     const CContextClient* client,
851                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
852   {
853     int serverSize = client->serverSize;
854
855     std::vector<CDomain*> domList = getDomains();
856     std::vector<CAxis*> axisList = getAxis();
857
858     // Some pre-calculations of global index on each element of current grid.
859     int nbElement = axis_domain_order.numElements();
860     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
861     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
862     std::vector<size_t> elementNGlobal(nbElement);
863     elementNGlobal[0] = 1;
864     size_t globalSize = 1;
865     for (int idx = 0; idx < nbElement; ++idx)
866     {
867       elementNGlobal[idx] = globalSize;
868       size_t elementSize;
869       size_t elementGlobalSize = 1;
870       if (2 == axis_domain_order(idx)) // This is domain
871       {
872         elementSize = domList[domainIdx]->i_index.numElements();
873         globalIndexElement[idx].resize(elementSize);
874         for (int jdx = 0; jdx < elementSize; ++jdx)
875         {
876           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
877         }
878         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
879         ++domainIdx;
880       }
881       else if (1 == axis_domain_order(idx))  // This is axis
882       {
883         elementSize = axisList[axisIdx]->index.numElements();
884         globalIndexElement[idx].resize(elementSize);
885         for (int jdx = 0; jdx < elementSize; ++jdx)
886         {
887           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
888         }
889         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
890         ++axisIdx;
891       }
892       else  // Of course, this is scalar
893       {
894         globalIndexElement[idx].resize(1);
895         globalIndexElement[idx](0) = 0;
896         elementGlobalSize = 1;
897       }
898       globalSize *= elementGlobalSize;
899     }
900
901     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
902     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
903     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
904     // Number of temporary distributed global index held by each client for each server
905     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
906     CArray<int,1> nbIndexOnServerTmp(serverSize);
907     for (int idx = 0; idx < nbElement; ++idx)
908     {
909       nbIndexOnServer = 0;
910       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
911       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
912       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
913       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
914       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
915       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
916                                                                    ite = globalIndexElementOnServerMap.end(), it;
917       for (it = itb; it != ite; ++it)
918       {
919         const std::vector<int>& tmp = it->second;
920         nbIndexOnServerTmp = 0;
921         for (int i = 0; i < tmp.size(); ++i)
922         {
923           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
924         }
925         nbIndexOnServer += nbIndexOnServerTmp;
926       }
927
928       for (int i = 0; i < serverSize; ++i)
929       {
930         if (0 != nbIndexOnServer(i))
931         {
932           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
933           elementOnServer[idx][i] = true;
934         }
935       }
936
937     nbIndexOnServer = 0;
938     for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
939     {
940       it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
941       if (it != ite)
942       {
943         const std::vector<int>& tmp = it->second;
944         nbIndexOnServerTmp = 0;
945         for (int i = 0; i < tmp.size(); ++i)
946         {
947           if (0 == nbIndexOnServerTmp(tmp[i]))
948           {
949             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
950             ++nbIndexOnServerTmp(tmp[i]);
951           }
952         }
953         nbIndexOnServer += nbIndexOnServerTmp;
954       }
955     }
956   }
957
958    // Determine server which contain global source index
959    std::vector<bool> intersectedProc(serverSize, true);
960    for (int idx = 0; idx < nbElement; ++idx)
961    {
962      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
963                     intersectedProc.begin(), intersectedProc.begin(),
964                     std::logical_and<bool>());
965    }
966
967    std::vector<int> srcRank;
968    for (int idx = 0; idx < serverSize; ++idx)
969    {
970      if (intersectedProc[idx]) srcRank.push_back(idx);
971    }
972
973    // Compute the global index of grid from global index of each element.
974    for (int i = 0; i < srcRank.size(); ++i)
975    {
976      size_t ssize = 1;
977      int rankSrc = srcRank[i];
978      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
979      std::vector<size_t> currentIndex(nbElement,0);
980      for (int idx = 0; idx < nbElement; ++idx)
981      {
982        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
983        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
984      }
985      globalIndexOnServer[rankSrc].resize(ssize);
986
987      std::vector<int> idxLoop(nbElement,0);
988      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
989      size_t idx = 0;
990      while (idx < ssize)
991      {
992        for (int ind = 0; ind < nbElement; ++ind)
993        {
994          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
995          {
996            idxLoop[ind] = 0;
997            ++idxLoop[ind+1];
998          }
999
1000          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
1001        }
1002
1003        for (int ind = 0; ind < innnerLoopSize; ++ind)
1004        {
1005          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
1006          size_t globalSrcIndex = 0;
1007          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
1008          {
1009            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
1010          }
1011          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
1012          ++idx;
1013          ++idxLoop[0];
1014        }
1015      }
1016    }
1017   }
1018   //----------------------------------------------------------------
1019
1020   CGrid* CGrid::createGrid(CDomain* domain)
1021   {
1022      std::vector<CDomain*> vecDom(1, domain);
1023      std::vector<CAxis*> vecAxis;
1024
1025      return createGrid(vecDom, vecAxis);
1026   }
1027
1028   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
1029   {
1030      std::vector<CDomain*> vecDom(1, domain);
1031      std::vector<CAxis*> vecAxis(1, axis);
1032
1033      return createGrid(vecDom, vecAxis);
1034   }
1035
1036   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1037                            const CArray<int,1>& axisDomainOrder)
1038   {
1039     std::vector<CScalar*> vecScalar;
1040     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
1041   }
1042
1043   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1044                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1045   {
1046     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
1047   }
1048
1049   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1050                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1051   {
1052      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1053        ERROR("CGrid* CGrid::createGrid(...)",
1054              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1055              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1056
1057      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
1058      grid->setDomainList(domains);
1059      grid->setAxisList(axis);
1060      grid->setScalarList(scalars);
1061
1062      // By default, domains are always the first elements of a grid
1063      if (0 == axisDomainOrder.numElements())
1064      {
1065        int size = domains.size() + axis.size() + scalars.size();
1066        int nb = 0;
1067        grid->axis_domain_order.resize(size);
1068        for (int i = 0; i < size; ++i)
1069        {
1070          if (i < domains.size()) {
1071            grid->axis_domain_order(i) = 2;
1072
1073          }
1074          else if ((scalars.size() < (size-nb)) < size) {
1075            grid->axis_domain_order(i) = 1;
1076          }
1077          else
1078            grid->axis_domain_order(i) = 0;
1079          ++nb;
1080        }
1081      }
1082      else
1083      {
1084        grid->axis_domain_order.resize(axisDomainOrder.numElements());
1085        grid->axis_domain_order = axisDomainOrder;
1086      }
1087
1088      grid->solveDomainAxisRefInheritance(true);
1089
1090      return grid;
1091   }
1092
1093   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
1094   {
1095     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
1096     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
1097     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
1098
1099     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
1100     {
1101       CDomain* domain = CDomain::createDomain();
1102       domain->duplicateAttributes(domainSrcTmp[idx]);
1103       domain->duplicateTransformation(domainSrcTmp[idx]);
1104       domain->solveRefInheritance(true);
1105       domain->solveInheritanceTransformation();
1106       domainSrc.push_back(domain);
1107     }
1108
1109     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
1110     {
1111       CAxis* axis = CAxis::createAxis();
1112       axis->duplicateAttributes(axisSrcTmp[idx]);
1113       axis->duplicateTransformation(axisSrcTmp[idx]);
1114       axis->solveRefInheritance(true);
1115       axis->solveInheritanceTransformation();
1116       axisSrc.push_back(axis);
1117     }
1118
1119     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
1120     {
1121       CScalar* scalar = CScalar::createScalar();
1122       scalar->duplicateAttributes(scalarSrcTmp[idx]);
1123       scalar->duplicateTransformation(scalarSrcTmp[idx]);
1124       scalar->solveRefInheritance(true);
1125       scalar->solveInheritanceTransformation();
1126       scalarSrc.push_back(scalar);
1127     }
1128
1129      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
1130
1131      return grid;
1132   }
1133
1134   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1135                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1136   {
1137      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1138        ERROR("CGrid* CGrid::generateId(...)",
1139              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1140              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1141
1142      std::ostringstream id;
1143
1144      if (domains.empty() && axis.empty() && !scalars.empty())
1145        id << "__scalar_";
1146
1147      if (0 != (domains.size() + axis.size() + scalars.size()))
1148      {
1149        id << "__grid";
1150
1151        if (0 == axisDomainOrder.numElements())
1152        {
1153          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
1154          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
1155          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
1156        }
1157        else
1158        {
1159          size_t iDomain = 0, iAxis = 0, iScalar = 0;
1160          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
1161          {
1162            if (2 == axisDomainOrder(i))
1163              id << "_" << domains[iDomain++]->getId();
1164            else if (1 == axisDomainOrder(i))
1165              id << "_" << axis[iAxis++]->getId();
1166            else
1167              id << "_" << scalars[iScalar++]->getId();
1168          }
1169        }
1170
1171        id << "__";
1172      }
1173
1174      return id.str();
1175   }
1176
1177   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
1178   {
1179     StdString idSrc  = gridSrc->getId();
1180     StdString idDest = gridDest->getId();
1181
1182     std::ostringstream id;
1183     id << idSrc << "__" << idDest;
1184
1185     return id.str();
1186   }
1187
1188   //----------------------------------------------------------------
1189
1190   CDomainGroup* CGrid::getVirtualDomainGroup() const
1191   {
1192     return this->vDomainGroup_;
1193   }
1194
1195   CAxisGroup* CGrid::getVirtualAxisGroup() const
1196   {
1197     return this->vAxisGroup_;
1198   }
1199
1200   CScalarGroup* CGrid::getVirtualScalarGroup() const
1201   {
1202     return this->vScalarGroup_;
1203   }
1204
1205/*
1206   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
1207   {
1208     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
1209     StdSize numElements = stored.numElements();
1210     for (StdSize n = 0; n < numElements; ++n)
1211     {
1212       field[out_i(n)] = stored(n);
1213     }
1214   }
1215
1216   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
1217   {
1218     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
1219     StdSize numElements = stored.numElements();
1220     for (StdSize n = 0; n < numElements; ++n)
1221     {
1222       stored(n) = field[out_i(n)];
1223     }
1224   }
1225
1226   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
1227   {
1228     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
1229     StdSize numElements = stored.numElements();
1230     for (StdSize n = 0; n < numElements; ++n)
1231     {
1232       field[out_i(n)] = stored(n);
1233     }
1234   }
1235*/
1236   //----------------------------------------------------------------
1237
1238   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
1239   {
1240      const StdSize size = storeIndex_client.numElements();
1241
1242      stored.resize(size);
1243      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1244   }
1245
1246   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
1247   {
1248      const StdSize size = storeIndex_client.numElements();
1249
1250      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
1251   }
1252
1253   void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) const
1254   {
1255      const std::vector<int>& localMaskedDataIndex = clientDistribution_->getLocalMaskedDataIndexOnClient();
1256      const int size = localMaskedDataIndex.size();
1257     
1258      for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i];
1259   }
1260
1261  void CGrid::computeClientIndexScalarGrid()
1262  {
1263    CContext* context = CContext::getCurrent();   
1264//    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; // This should be changed soon
1265//    for (int p = 0; p < nbSrvPools; ++p)
1266    {
1267//      CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client)
1268//                                                    : context->client;
1269      CContextClient* client = context->client;
1270
1271      int rank = client->clientRank;
1272
1273      clientDistribution_ = new CDistributionClient(rank, this);
1274
1275      storeIndex_client.resize(1);
1276      storeIndex_client(0) = 0;     
1277
1278      if (0 != serverDistribution_)
1279      {
1280        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
1281                                               ite = outGlobalIndexFromClient.end(), it;
1282        for (it = itb; it != ite; ++it)
1283        {
1284          int rank = it->first;
1285          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1286          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1287          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
1288          if (1 != globalIndex.numElements())
1289            ERROR("void CGrid::computeClientIndexScalarGrid()",
1290              << "Something wrong happened. "
1291              << "Number of received global index on scalar grid should equal to 1" 
1292              << "Number of received global index " << globalIndex.numElements() << ".");
1293
1294          localIndex(0) = globalIndex(0);
1295        }
1296      }
1297    }
1298  }
1299
1300  void CGrid::computeConnectedClientsScalarGrid()
1301  {
1302    CContext* context = CContext::getCurrent();   
1303    int nbSrvPools = (context->clientPrimServer.size()==0) ? 1 : context->clientPrimServer.size();
1304    connectedServerRank_.clear();
1305    connectedDataSize_.clear();
1306    nbSenders.clear();
1307
1308    for (int p = 0; p < nbSrvPools; ++p)
1309    {
1310      CContextClient* client = (context->clientPrimServer.size()==0) ? context->client : context->clientPrimServer[p];
1311      int receiverSize = client->serverSize;
1312
1313//      connectedServerRank_[client].clear();
1314
1315      if (connectedServerRank_.find(receiverSize)==connectedServerRank_.end())
1316      {
1317        if (client->isServerLeader())
1318        {
1319          const std::list<int>& ranks = client->getRanksServerLeader();
1320          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1321          {
1322            int rank = *itRank;
1323            int nb = 1;
1324            connectedServerRank_[receiverSize].push_back(rank);
1325            connectedDataSize_[receiverSize][rank] = nb;
1326            nbSenders[receiverSize][rank] = nb;
1327          }
1328        }
1329        else
1330        {
1331          const std::list<int>& ranks = client->getRanksServerNotLeader();
1332          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1333          {
1334            int rank = *itRank;
1335            int nb = 1;
1336            connectedServerRank_[receiverSize].push_back(rank);
1337            connectedDataSize_[receiverSize][rank] = nb;
1338            nbSenders[receiverSize][rank] = nb;
1339          }
1340        }
1341      }
1342      isDataDistributed_ = false;
1343    }
1344  }
1345
1346  void CGrid::sendIndexScalarGrid()
1347  {
1348    CContext* context = CContext::getCurrent();
1349    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1350    storeIndex_toSrv.clear();
1351
1352    for (int p = 0; p < nbSrvPools; ++p)
1353    {
1354      CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client;
1355      int receiverSize = client->serverSize;
1356
1357      CEventClient event(getType(), EVENT_ID_INDEX);
1358      list<CMessage> listMsg;
1359      list<CArray<size_t,1> > listOutIndex;
1360
1361      if (client->isServerLeader())
1362      {
1363        const std::list<int>& ranks = client->getRanksServerLeader();
1364        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1365        {
1366          int rank = *itRank;
1367          int nb = 1;
1368          storeIndex_toSrv[client].insert(std::make_pair(rank, CArray<int,1>(nb)));
1369          listOutIndex.push_back(CArray<size_t,1>(nb));
1370
1371          CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank];
1372          CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1373
1374          for (int k = 0; k < nb; ++k)
1375          {
1376            outGlobalIndexOnServer(k) = 0;
1377            outLocalIndexToServer(k)  = 0;
1378          }
1379
1380          if (context->hasClient && !context->hasServer)
1381            storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1382
1383          listMsg.push_back(CMessage());
1384          listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
1385
1386          event.push(rank, 1, listMsg.back());
1387        }
1388        client->sendEvent(event);
1389      }
1390      else
1391      {
1392        const std::list<int>& ranks = client->getRanksServerNotLeader();
1393        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1394        {
1395          int rank = *itRank;
1396          int nb = 1;         
1397          CArray<int, 1> outLocalIndexToServer(nb);
1398          for (int k = 0; k < nb; ++k)
1399          {
1400            outLocalIndexToServer(k)  = 0;
1401          }
1402
1403          if (context->hasClient && !context->hasServer)
1404            storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1405        }
1406        client->sendEvent(event);
1407      }
1408    }
1409  }
1410
1411  void CGrid::sendIndex(void)
1412  {
1413    CContext* context = CContext::getCurrent();
1414    int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size();
1415    storeIndex_toSrv.clear();
1416    for (int p = 0; p < nbSrvPools; ++p)
1417    {
1418      CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p];
1419      int receiverSize = client->serverSize;
1420
1421      CEventClient event(getType(), EVENT_ID_INDEX);
1422      int rank;
1423      list<CMessage> listMsg;
1424      list<CArray<size_t,1> > listOutIndex;
1425      const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
1426      CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex,
1427                                                              iteIndex = globalLocalIndexSendToServer.end();
1428      itIndex = itbIndex;                                                             
1429
1430      if (!doGridHaveDataDistributed(client))
1431      {
1432        if (client->isServerLeader())
1433        {
1434          int indexSize = globalLocalIndexSendToServer.size();
1435          CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1436          CArray<int,1> outLocalIndexToServer(indexSize);
1437          for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1438          {
1439            outGlobalIndexOnServer(idx) = itIndex->first;
1440            outLocalIndexToServer(idx) = itIndex->second;
1441          }
1442
1443          const std::list<int>& ranks = client->getRanksServerLeader();
1444          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1445          {
1446            storeIndex_toSrv[client].insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1447            if (context->hasClient && !context->hasServer)
1448              storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1449           
1450            listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1451
1452            listMsg.push_back(CMessage());
1453            listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1454
1455            event.push(*itRank, 1, listMsg.back());
1456          }
1457          client->sendEvent(event);
1458        }
1459        else
1460        {
1461           int indexSize = globalLocalIndexSendToServer.size();
1462           CArray<int,1> outLocalIndexToServer(indexSize);
1463           for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1464           {
1465             outLocalIndexToServer(idx) = itIndex->second;
1466           }
1467
1468           const std::list<int>& ranks = client->getRanksServerNotLeader();
1469           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1470           {
1471             storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1472           }
1473           client->sendEvent(event);
1474         }
1475      }
1476      else
1477      {
1478        CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
1479        itGlobalMap = globalIndexOnServer_[receiverSize].begin();
1480        iteGlobalMap = globalIndexOnServer_[receiverSize].end();
1481
1482        std::map<int,std::vector<int> >localIndexTmp;
1483        std::map<int,std::vector<size_t> > globalIndexTmp;
1484        for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1485        {
1486          int serverRank = itGlobalMap->first;
1487          int indexSize = itGlobalMap->second.size();
1488          const std::vector<size_t>& indexVec = itGlobalMap->second;
1489          for (int idx = 0; idx < indexSize; ++idx)
1490          {
1491            itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
1492            if (iteIndex != itIndex)
1493            {
1494              globalIndexTmp[serverRank].push_back(itIndex->first);
1495              localIndexTmp[serverRank].push_back(itIndex->second);
1496            }
1497          }
1498        }
1499
1500        for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns)
1501        {
1502          rank = connectedServerRank_[receiverSize][ns];
1503          int nb = 0;
1504          if (globalIndexTmp.end() != globalIndexTmp.find(rank))
1505            nb = globalIndexTmp[rank].size();
1506
1507          storeIndex_toSrv[client].insert(make_pair(rank, CArray<int,1>(nb)));
1508          listOutIndex.push_back(CArray<size_t,1>(nb));
1509
1510          CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank];
1511          CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1512
1513          for (int k = 0; k < nb; ++k)
1514          {
1515            outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1516            outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1517          }
1518
1519          storeIndex_fromSrv.insert(make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1520          listMsg.push_back(CMessage());
1521          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1522
1523          event.push(rank, nbSenders[receiverSize][rank], listMsg.back());
1524        }
1525
1526        client->sendEvent(event);
1527      }
1528    }
1529  }
1530
1531  void CGrid::recvIndex(CEventServer& event)
1532  {
1533    string gridId;
1534    vector<int> ranks;
1535    vector<CBufferIn*> buffers;
1536
1537    list<CEventServer::SSubEvent>::iterator it;
1538    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1539    {
1540      ranks.push_back(it->rank);
1541      CBufferIn* buffer = it->buffer;
1542      *buffer >> gridId;
1543      buffers.push_back(buffer);
1544    }
1545    get(gridId)->recvIndex(ranks, buffers);
1546  }
1547
1548  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1549  {
1550    CContext* context = CContext::getCurrent();
1551
1552    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
1553    nbSrvPools = 1;   
1554    nbReadSenders.clear();
1555    for (int p = 0; p < nbSrvPools; ++p)
1556    {
1557      CContextServer* server = (!context->hasClient) ? context->server : context->serverPrimServer[p];
1558      CContextClient* client = context->client;   //(!context->hasClient) ? context->client : context->clientPrimServer[p];
1559     
1560      int idx = 0, numElement = axis_domain_order.numElements();
1561      int ssize = numElement;
1562      std::vector<int> indexMap(numElement);
1563      for (int i = 0; i < numElement; ++i)
1564      {
1565        indexMap[i] = idx;
1566        if (2 == axis_domain_order(i))
1567        {
1568          ++ssize;
1569          idx += 2;
1570        }
1571        else
1572          ++idx;
1573      }
1574
1575      for (int n = 0; n < ranks.size(); n++)
1576      {
1577        int rank = ranks[n];
1578        CBufferIn& buffer = *buffers[n];
1579
1580        buffer >> isDataDistributed_ >> isCompressible_;
1581        size_t dataSize = 0;
1582
1583        if (0 == serverDistribution_)
1584        {
1585          int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1586          std::vector<CDomain*> domainList = getDomains();
1587          std::vector<CAxis*> axisList = getAxis();
1588          std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize), nGlobElement(numElement);
1589          std::vector<CArray<int,1> > globalZoomIndex(numElement);
1590          for (int i = 0; i < numElement; ++i)
1591          {
1592            nGlobElement[i] = globalSize;
1593            if (2 == axis_domain_order(i)) //domain
1594            {
1595              nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin;
1596              nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni;
1597              nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;             
1598              nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1599
1600              nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
1601              nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj;
1602              nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;             
1603              nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1604
1605              {
1606                int count = 0;
1607                globalZoomIndex[i].resize(nZoomSize[indexMap[i]]*nZoomSize[indexMap[i]+1]);
1608                for (int jdx = 0; jdx < nZoomSize[indexMap[i]+1]; ++jdx)
1609                  for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)               
1610                  {
1611                    globalZoomIndex[i](count) = (nZoomBegin[indexMap[i]] + idx) + (nZoomBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
1612                    ++count;
1613                  }
1614              }
1615
1616              ++domainId;
1617            }
1618            else if (1 == axis_domain_order(i)) // axis
1619            {
1620              nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin;
1621              nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_n;
1622              nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;             
1623              nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
1624              if (axisList[axisId]->zoomByIndex())
1625              {
1626                globalZoomIndex[i].reference(axisList[axisId]->zoom_index);               
1627              }
1628              else
1629              {
1630                globalZoomIndex[i].resize(nZoomSize[indexMap[i]]);
1631                for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)
1632                  globalZoomIndex[i](idx) = nZoomBegin[indexMap[i]] + idx;
1633              }
1634
1635              ++axisId;
1636            }
1637            else // scalar
1638            { 
1639              nZoomBegin[indexMap[i]] = 0;
1640              nZoomSize[indexMap[i]]  = 1;
1641              nZoomBeginGlobal[indexMap[i]] = 0;             
1642              nGlob[indexMap[i]] = 1;
1643              globalZoomIndex[i].resize(1);
1644              globalZoomIndex[i](0) = 0;
1645              ++scalarId;
1646            }
1647          }
1648          dataSize = 1;
1649
1650          for (int i = 0; i < nZoomSize.size(); ++i)
1651            dataSize *= nZoomSize[i];
1652          serverDistribution_ = new CDistributionServer(server->intraCommRank, 
1653                                                        globalZoomIndex, axis_domain_order,
1654                                                        nZoomBegin, nZoomSize, nZoomBeginGlobal, nGlob);
1655        }
1656
1657        CArray<size_t,1> outIndex;
1658        buffer >> outIndex;
1659        outGlobalIndexFromClient.insert(std::make_pair(rank, outIndex));       
1660
1661        if (doGridHaveDataDistributed(client))
1662        {}
1663        else
1664        {
1665          // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
1666          // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
1667          dataSize = serverDistribution_->getGridSize();
1668        }
1669        writtenDataSize_ += dataSize;
1670      }
1671
1672
1673      // Compute mask of the current grid
1674      {
1675        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1676        std::vector<CDomain*> domainList = getDomains();
1677        std::vector<CAxis*> axisList = getAxis();
1678        int dimSize = 2 * domainList.size() + axisList.size();
1679        std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize);       
1680        for (int i = 0; i < numElement; ++i)
1681        {         
1682          if (2 == axis_domain_order(i)) //domain
1683          {
1684            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
1685            nSize[indexMap[i]]  = domainList[domainId]->ni;
1686            nBeginGlobal[indexMap[i]] = 0;             
1687            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1688
1689            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
1690            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
1691            nBeginGlobal[indexMap[i] + 1] = 0;             
1692            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1693
1694            ++domainId;
1695          }
1696          else if (1 == axis_domain_order(i)) // axis
1697          {
1698            nBegin[indexMap[i]] = axisList[axisId]->begin;
1699            nSize[indexMap[i]]  = axisList[axisId]->n;
1700            nBeginGlobal[indexMap[i]] = 0;             
1701            nGlob[indexMap[i]] = axisList[axisId]->n_glo;             
1702            ++axisId;
1703          }
1704          else // scalar
1705          { 
1706          }
1707        }
1708       
1709        if (nSize.empty()) // Scalar grid
1710        {
1711          nBegin.push_back(0);
1712          nSize.push_back(1);
1713          nBeginGlobal.push_back(0);             
1714          nGlob.push_back(1); 
1715        }
1716
1717        modifyMaskSize(nSize, false);
1718
1719        // These below codes are reserved for future
1720        CDistributionServer srvDist(server->intraCommRank, nBegin, nSize, nBeginGlobal, nGlob); 
1721        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
1722                                               ite = outGlobalIndexFromClient.end(), it; 
1723        const CDistributionServer::GlobalLocalMap&  globalLocalMask = srvDist.getGlobalLocalIndex();
1724        CDistributionServer::GlobalLocalMap::const_iterator itSrv;
1725        size_t nb = 0;
1726        for (it = itb; it != ite; ++it)
1727        {
1728          CArray<size_t,1>& globalInd = it->second;
1729          for (size_t idx = 0; idx < globalInd.numElements(); ++idx)
1730          {
1731            if (globalLocalMask.end() != globalLocalMask.find(globalInd(idx))) ++nb;
1732          }
1733        }
1734       
1735        CArray<int,1> indexToModify(nb);
1736        nb = 0;   
1737        for (it = itb; it != ite; ++it)
1738        {
1739          CArray<size_t,1>& globalInd = it->second;
1740          for (size_t idx = 0; idx < globalInd.numElements(); ++idx)
1741          {
1742            itSrv = globalLocalMask.find(globalInd(idx));
1743            if (globalLocalMask.end() != itSrv) 
1744            {
1745              indexToModify(nb) = itSrv->second;
1746              ++nb;
1747            }
1748          }
1749        }
1750
1751        modifyMask(indexToModify, true);
1752      }
1753
1754      if (isScalarGrid()) return;
1755
1756      nbReadSenders[client] = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1757    }
1758  }
1759
1760  /*
1761     Compute on the fly the global dimension of a grid with its elements
1762     \param[in/out] globalDim global dimension of grid
1763     \param[in] domains list of its domains
1764     \param[in] axiss list of its axis
1765     \param[in] scalars list of its scalars
1766     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1767     \return The dimension of which we do distribution (often for server)
1768  */
1769  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1770                                        const std::vector<CDomain*> domains,
1771                                        const std::vector<CAxis*> axis,
1772                                        const std::vector<CScalar*> scalars,
1773                                        const CArray<int,1>& axisDomainOrder)
1774  {
1775    globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1776    int positionDimensionDistributed = 1;
1777    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1778    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1779    {
1780      if (2 == axisDomainOrder(i))
1781      {
1782        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1783        {
1784          positionDimensionDistributed = idx;
1785        }
1786        else
1787        {
1788          positionDimensionDistributed = idx +1;
1789        }
1790
1791        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
1792        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
1793
1794        ++idxDomain;
1795        idx += 2;
1796      }
1797      else if (1 == axisDomainOrder(i))
1798      {
1799        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
1800        ++idxAxis;
1801        ++idx;
1802      }
1803      else
1804      {
1805        globalDim[idx] = 1;
1806        ++idxScalar;
1807        ++idx;
1808      }
1809    }
1810
1811    return positionDimensionDistributed;
1812  }
1813
1814  // Retrieve the global dimension of grid
1815  std::vector<int> CGrid::getGlobalDimension()
1816  {
1817    std::vector<int> globalDim;
1818    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
1819
1820    return globalDim;
1821  }
1822
1823  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
1824  int CGrid::getDistributedDimension()
1825  {
1826    std::vector<int> globalDim;
1827    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
1828  }
1829
1830  bool CGrid::isScalarGrid() const
1831  {
1832    return (axisList_.empty() && domList_.empty());
1833  }
1834
1835  /*!
1836    Verify whether one server need to write data
1837    There are some cases on which one server has nodata to write. For example, when we
1838    just only want to zoom on a domain.
1839  */
1840  bool CGrid::doGridHaveDataToWrite()
1841  {
1842     return (0 != writtenDataSize_);
1843  }
1844
1845  /*!
1846    Return size of data which is written on each server
1847    Whatever dimension of a grid, data which are written on server must be presented as
1848    an one dimension array.
1849    \return size of data written on server
1850  */
1851  size_t CGrid::getWrittenDataSize() const
1852  {
1853    return writtenDataSize_;
1854  }
1855
1856  /*!
1857    Returns the number of indexes written by each server.
1858    \return the number of indexes written by each server
1859  */
1860  int CGrid::getNumberWrittenIndexes() const
1861  {
1862    return numberWrittenIndexes_;
1863  }
1864
1865  /*!
1866    Returns the total number of indexes written by the servers.
1867    \return the total number of indexes written by the servers
1868  */
1869  int CGrid::getTotalNumberWrittenIndexes() const
1870  {
1871    return totalNumberWrittenIndexes_;
1872  }
1873
1874  /*!
1875    Returns the offset of indexes written by each server.
1876    \return the offset of indexes written by each server
1877  */
1878  int CGrid::getOffsetWrittenIndexes() const
1879  {
1880    return offsetWrittenIndexes_;
1881  }
1882
1883  CDistributionServer* CGrid::getDistributionServer()
1884  {
1885    return serverDistribution_;
1886  }
1887
1888  CDistributionClient* CGrid::getDistributionClient()
1889  {
1890    return clientDistribution_;
1891  }
1892
1893  bool CGrid::doGridHaveDataDistributed(CContextClient* client)
1894  {
1895    if (isScalarGrid()) return false;
1896    else if (0 != client)
1897    {
1898      return  (isDataDistributed_ ||  (1 != client->clientSize) || (1 != client->serverSize));
1899    }
1900    else
1901      return isDataDistributed_;   
1902  }
1903
1904   /*!
1905   \brief Dispatch event received from client
1906      Whenever a message is received in buffer of server, it will be processed depending on
1907   its event type. A new event type should be added in the switch list to make sure
1908   it processed on server side.
1909   \param [in] event: Received message
1910   */
1911  bool CGrid::dispatchEvent(CEventServer& event)
1912  {
1913
1914    if (SuperClass::dispatchEvent(event)) return true;
1915    else
1916    {
1917      switch(event.type)
1918      {
1919        case EVENT_ID_INDEX :
1920          recvIndex(event);
1921          return true;
1922          break;
1923
1924         case EVENT_ID_ADD_DOMAIN :
1925           recvAddDomain(event);
1926           return true;
1927           break;
1928
1929         case EVENT_ID_ADD_AXIS :
1930           recvAddAxis(event);
1931           return true;
1932           break;
1933
1934         case EVENT_ID_ADD_SCALAR :
1935           recvAddScalar(event);
1936           return true;
1937           break;
1938        default :
1939          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1940                << "Unknown Event");
1941          return false;
1942      }
1943    }
1944  }
1945
1946   ///---------------------------------------------------------------
1947
1948   CDomain* CGrid::addDomain(const std::string& id)
1949   {
1950     order_.push_back(2);
1951     axis_domain_order.resize(order_.size());
1952     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1953     return vDomainGroup_->createChild(id);
1954   }
1955
1956   CAxis* CGrid::addAxis(const std::string& id)
1957   {
1958     order_.push_back(1);
1959     axis_domain_order.resize(order_.size());
1960     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1961     return vAxisGroup_->createChild(id);
1962   }
1963
1964   CScalar* CGrid::addScalar(const std::string& id)
1965   {
1966     order_.push_back(0);
1967     axis_domain_order.resize(order_.size());
1968     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1969     return vScalarGroup_->createChild(id);
1970   }
1971
1972   //! Change virtual field group to a new one
1973   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1974   {
1975      this->vDomainGroup_ = newVDomainGroup;
1976   }
1977
1978   //! Change virtual variable group to new one
1979   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1980   {
1981      this->vAxisGroup_ = newVAxisGroup;
1982   }
1983
1984   //! Change virtual variable group to new one
1985   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1986   {
1987      this->vScalarGroup_ = newVScalarGroup;
1988   }
1989
1990   /*!
1991   \brief Send a message to create a domain on server side
1992   \param[in] id String identity of domain that will be created on server
1993   */
1994   void CGrid::sendAddDomain(const string& id)
1995   {
1996      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN);
1997   }
1998
1999   /*!
2000   \brief Send a message to create an axis on server side
2001   \param[in] id String identity of axis that will be created on server
2002   */
2003   void CGrid::sendAddAxis(const string& id)
2004   {
2005      sendAddItem(id, (int)EVENT_ID_ADD_AXIS);
2006   }
2007
2008   /*!
2009   \brief Send a message to create a scalar on server side
2010   \param[in] id String identity of scalar that will be created on server
2011   */
2012   void CGrid::sendAddScalar(const string& id)
2013   {
2014      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR);
2015   }
2016
2017   /*!
2018   \brief Receive a message annoucing the creation of a domain on server side
2019   \param[in] event Received event
2020   */
2021   void CGrid::recvAddDomain(CEventServer& event)
2022   {
2023
2024      CBufferIn* buffer = event.subEvents.begin()->buffer;
2025      string id;
2026      *buffer >> id;
2027      get(id)->recvAddDomain(*buffer);
2028   }
2029
2030   /*!
2031   \brief Receive a message annoucing the creation of a domain on server side
2032   \param[in] buffer Buffer containing message
2033   */
2034   void CGrid::recvAddDomain(CBufferIn& buffer)
2035   {
2036      string id;
2037      buffer >> id;
2038      addDomain(id);
2039   }
2040
2041   /*!
2042   \brief Receive a message annoucing the creation of an axis on server side
2043   \param[in] event Received event
2044   */
2045   void CGrid::recvAddAxis(CEventServer& event)
2046   {
2047
2048      CBufferIn* buffer = event.subEvents.begin()->buffer;
2049      string id;
2050      *buffer >> id;
2051      get(id)->recvAddAxis(*buffer);
2052   }
2053
2054   /*!
2055   \brief Receive a message annoucing the creation of an axis on server side
2056   \param[in] buffer Buffer containing message
2057   */
2058   void CGrid::recvAddAxis(CBufferIn& buffer)
2059   {
2060      string id;
2061      buffer >> id;
2062      addAxis(id);
2063   }
2064
2065   /*!
2066   \brief Receive a message annoucing the creation of an scalar on server side
2067   \param[in] event Received event
2068   */
2069   void CGrid::recvAddScalar(CEventServer& event)
2070   {
2071
2072      CBufferIn* buffer = event.subEvents.begin()->buffer;
2073      string id;
2074      *buffer >> id;
2075      get(id)->recvAddScalar(*buffer);
2076   }
2077
2078   /*!
2079   \brief Receive a message annoucing the creation of an scalar on server side
2080   \param[in] buffer Buffer containing message
2081   */
2082   void CGrid::recvAddScalar(CBufferIn& buffer)
2083   {
2084      string id;
2085      buffer >> id;
2086      addScalar(id);
2087   }
2088
2089  /*!
2090  \brief Solve domain and axis references
2091  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
2092  all attributes from their parents, they should be processed with this function
2093  \param[in] apply inherit all attributes of parents (true)
2094  */
2095  void CGrid::solveDomainAxisRefInheritance(bool apply)
2096  {
2097    CContext* context = CContext::getCurrent();
2098    unsigned int vecSize, i;
2099    std::vector<StdString>::iterator it, itE;
2100    setDomainList();
2101    it = domList_.begin(); itE = domList_.end();
2102    for (; it != itE; ++it)
2103    {
2104      CDomain* pDom = CDomain::get(*it);
2105      if (context->hasClient && !context->hasServer)     
2106      {
2107        pDom->solveRefInheritance(apply);
2108        pDom->solveInheritanceTransformation();
2109      }
2110    }
2111
2112    setAxisList();
2113    it = axisList_.begin(); itE = axisList_.end();
2114    for (; it != itE; ++it)
2115    {
2116      CAxis* pAxis = CAxis::get(*it);
2117      if (context->hasClient && !context->hasServer)
2118      {
2119        pAxis->solveRefInheritance(apply);
2120        pAxis->solveInheritanceTransformation();
2121      }
2122    }
2123
2124    setScalarList();
2125    it = scalarList_.begin(); itE = scalarList_.end();
2126    for (; it != itE; ++it)
2127    {
2128      CScalar* pScalar = CScalar::get(*it);
2129      if (context->hasClient && !context->hasServer)
2130      {
2131        pScalar->solveRefInheritance(apply);
2132        pScalar->solveInheritanceTransformation();
2133      }
2134    }
2135  }
2136
2137  bool CGrid::isTransformed()
2138  {
2139    return isTransformed_;
2140  }
2141
2142  void CGrid::setTransformed()
2143  {
2144    isTransformed_ = true;
2145  }
2146
2147  CGridTransformation* CGrid::getTransformations()
2148  {
2149    return transformations_;
2150  }
2151
2152  void CGrid::addTransGridSource(CGrid* gridSrc)
2153  {
2154    if (gridSrc_.end() == gridSrc_.find(gridSrc))
2155      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
2156  }
2157
2158  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
2159  {
2160    return gridSrc_;
2161  }
2162
2163  /*!
2164     Complete all the necessary (and lacking) attributes of a grid
2165     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
2166  */
2167  void CGrid::completeGrid(CGrid* transformGridSrc)
2168  {
2169    if (0 != transformGridSrc)
2170    {
2171      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2172      {
2173        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
2174             << "Two grids have different number of elements. " << std::endl
2175             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2176             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2177      }
2178    }
2179
2180    if (isGenerated()) return;
2181    setGenerated();
2182
2183    CGridGenerate gridGenerate(this, transformGridSrc);
2184    gridGenerate.completeGrid();
2185  }
2186
2187  bool CGrid::isGenerated()
2188  {
2189    return isGenerated_;
2190  }
2191
2192  void CGrid::setGenerated()
2193  {
2194    isGenerated_ = true;
2195  }
2196
2197  void CGrid::transformGrid(CGrid* transformGridSrc)
2198  {
2199    if (!transformGridSrc)
2200      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2201            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
2202
2203    if (isTransformed()) return;
2204    setTransformed();
2205    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2206    {
2207      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2208           << "Two grids have different number of elements. " << std::endl
2209           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2210           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2211    }
2212    else
2213    {
2214    }
2215
2216    transformations_ = new CGridTransformation(this, transformGridSrc);
2217    transformations_->computeAll();
2218    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
2219
2220    // Ok, now need to compute index of grid source
2221    transformGridSrc->checkMaskIndex(false);
2222  }
2223
2224  bool CGrid::hasTransform()
2225  {
2226    if (hasTransform_) return hasTransform_;
2227
2228    std::vector<CDomain*> domList = getDomains();
2229    std::vector<CAxis*> axisList = getAxis();
2230    std::vector<CScalar*> scalarList = getScalars();
2231
2232    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
2233    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
2234    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
2235
2236    return hasTransform_;
2237  }
2238
2239  /*!
2240  \brief Get the list of domain pointers
2241  \return list of domain pointers
2242  */
2243  std::vector<CDomain*> CGrid::getDomains()
2244  {
2245    std::vector<CDomain*> domList;
2246    if (!domList_.empty())
2247    {
2248      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
2249    }
2250    return domList;
2251  }
2252
2253  /*!
2254  \brief Get the list of  axis pointers
2255  \return list of axis pointers
2256  */
2257  std::vector<CAxis*> CGrid::getAxis()
2258  {
2259    std::vector<CAxis*> aList;
2260    if (!axisList_.empty())
2261      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
2262
2263    return aList;
2264  }
2265
2266  /*!
2267  \brief Get the list of  axis pointers
2268  \return list of axis pointers
2269  */
2270  std::vector<CScalar*> CGrid::getScalars()
2271  {
2272    std::vector<CScalar*> sList;
2273    if (!scalarList_.empty())
2274      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
2275
2276    return sList;
2277  }
2278
2279  /*!
2280  \brief Get domain pointer with index
2281  \return domain pointer
2282  */
2283  CDomain* CGrid::getDomain(int domainIndex)
2284  {
2285    std::vector<CDomain*> domainListP = this->getDomains();
2286    if (domainListP.empty())
2287    {
2288      ERROR("CGrid::getDomain(int domainIndex)",
2289            << "No domain associated to this grid. " << std::endl
2290            << "Grid id = " << this->getId());
2291    }
2292
2293    if (domainIndex >= domainListP.size() || (domainIndex < 0))
2294      ERROR("CGrid::getDomain(int domainIndex)",
2295            << "Domain with the index doesn't exist " << std::endl
2296            << "Grid id = " << this->getId() << std::endl
2297            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
2298
2299    return domainListP[domainIndex];
2300  }
2301
2302  /*!
2303  \brief Get the axis pointer with index
2304  \return axis pointer
2305  */
2306  CAxis* CGrid::getAxis(int axisIndex)
2307  {
2308    std::vector<CAxis*> axisListP = this->getAxis();
2309    if (axisListP.empty())
2310    {
2311      ERROR("CGrid::getDomain(int axisIndex)",
2312            << "No axis associated to this grid. " << std::endl
2313            << "Grid id = " << this->getId());
2314    }
2315
2316    if (axisIndex >= axisListP.size() || (axisIndex < 0))
2317      ERROR("CGrid::getDomain(int axisIndex)",
2318            << "Domain with the index doesn't exist " << std::endl
2319            << "Grid id = " << this->getId() << std::endl
2320            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
2321
2322    return axisListP[axisIndex];
2323  }
2324
2325  /*!
2326  \brief Get the a scalar pointer
2327  \return scalar pointer
2328  */
2329  CScalar* CGrid::getScalar(int scalarIndex)
2330  {
2331    std::vector<CScalar*> scalarListP = this->getScalars();
2332    if (scalarListP.empty())
2333    {
2334      ERROR("CGrid::getScalar(int scalarIndex)",
2335            << "No scalar associated to this grid. " << std::endl
2336            << "Grid id = " << this->getId());
2337    }
2338
2339    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
2340      ERROR("CGrid::getScalar(int scalarIndex)",
2341            << "Scalar with the index doesn't exist " << std::endl
2342            << "Grid id = " << this->getId() << std::endl
2343            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
2344
2345    return scalarListP[scalarIndex];
2346  }
2347
2348  /*!
2349  \brief Set domain(s) of a grid from a list
2350  \param[in] domains list of domains
2351  */
2352  void CGrid::setDomainList(const std::vector<CDomain*> domains)
2353  {
2354    if (isDomListSet) return;
2355    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2356    if (!domains.empty() && domList.empty())
2357    {
2358      for (int i = 0; i < domains.size(); ++i)
2359        this->getVirtualDomainGroup()->addChild(domains[i]);
2360      domList = this->getVirtualDomainGroup()->getAllChildren();
2361    }
2362
2363    if (!domList.empty())
2364    {
2365      int sizeDom = domList.size();
2366      domList_.resize(sizeDom);
2367      for (int i = 0; i < sizeDom; ++i)
2368      {
2369        domList_[i] = domList[i]->getId();
2370      }
2371      isDomListSet = true;
2372    }
2373
2374  }
2375
2376  /*!
2377  \brief Set axis(s) of a grid from a list
2378  \param[in] axis list of axis
2379  */
2380  void CGrid::setAxisList(const std::vector<CAxis*> axis)
2381  {
2382    if (isAxisListSet) return;
2383    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2384    if (!axis.empty() && aList.empty())
2385    {
2386      for (int i = 0; i < axis.size(); ++i)
2387        this->getVirtualAxisGroup()->addChild(axis[i]);
2388      aList = this->getVirtualAxisGroup()->getAllChildren();
2389    }
2390
2391    if (!aList.empty())
2392    {
2393      int sizeAxis = aList.size();
2394      axisList_.resize(sizeAxis);
2395      for (int i = 0; i < sizeAxis; ++i)
2396      {
2397        axisList_[i] = aList[i]->getId();
2398      }
2399      isAxisListSet = true;
2400    }
2401  }
2402
2403  /*!
2404  \brief Set scalar(s) of a grid from a list
2405  \param[in] scalars list of scalars
2406  */
2407  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
2408  {
2409    if (isScalarListSet) return;
2410    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2411    if (!scalars.empty() && sList.empty())
2412    {
2413      for (int i = 0; i < scalars.size(); ++i)
2414        this->getVirtualScalarGroup()->addChild(scalars[i]);
2415      sList = this->getVirtualScalarGroup()->getAllChildren();
2416    }
2417
2418    if (!sList.empty())
2419    {
2420      int sizeScalar = sList.size();
2421      scalarList_.resize(sizeScalar);
2422      for (int i = 0; i < sizeScalar; ++i)
2423      {
2424        scalarList_[i] = sList[i]->getId();
2425      }
2426      isScalarListSet = true;
2427    }
2428  }
2429
2430  /*!
2431  \brief Get list of id of domains
2432  \return id list of domains
2433  */
2434  std::vector<StdString> CGrid::getDomainList()
2435  {
2436    setDomainList();
2437    return domList_;
2438  }
2439
2440  /*!
2441  \brief Get list of id of axis
2442  \return id list of axis
2443  */
2444  std::vector<StdString> CGrid::getAxisList()
2445  {
2446    setAxisList();
2447    return axisList_;
2448  }
2449
2450  /*!
2451  \brief Get list of id of scalar
2452  \return id list of scalar
2453  */
2454  std::vector<StdString> CGrid::getScalarList()
2455  {
2456    setScalarList();
2457    return scalarList_;
2458  }
2459
2460  /*!
2461    Send all attributes of domains from client to server
2462  */
2463  void CGrid::sendAllDomains()
2464  {
2465    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2466    int dSize = domList.size();
2467    for (int i = 0; i < dSize; ++i)
2468    {
2469      sendAddDomain(domList[i]->getId());
2470      domList[i]->sendAllAttributesToServer();
2471    }
2472  }
2473
2474  /*!
2475    Send all attributes of axis from client to server
2476  */
2477  void CGrid::sendAllAxis()
2478  {
2479    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2480    int aSize = aList.size();
2481
2482    for (int i = 0; i < aSize; ++i)
2483    {
2484      sendAddAxis(aList[i]->getId());
2485      aList[i]->sendAllAttributesToServer();
2486    }
2487  }
2488
2489  /*!
2490    Send all attributes of scalars from client to server
2491  */
2492  void CGrid::sendAllScalars()
2493  {
2494    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2495    int sSize = sList.size();
2496
2497    for (int i = 0; i < sSize; ++i)
2498    {
2499      sendAddScalar(sList[i]->getId());
2500      sList[i]->sendAllAttributesToServer();
2501    }
2502  }
2503
2504  /*!
2505    Parse a grid, for now, it contains only domain, axis and scalar
2506  */
2507  void CGrid::parse(xml::CXMLNode& node)
2508  {
2509    SuperClass::parse(node);
2510
2511    if (node.goToChildElement())
2512    {
2513      StdString domainName("domain");
2514      StdString axisName("axis");
2515      StdString scalarName("scalar");
2516      do
2517      {
2518        if (node.getElementName() == domainName) {
2519          order_.push_back(2);
2520          this->getVirtualDomainGroup()->parseChild(node);
2521        }
2522        if (node.getElementName() == axisName) {
2523          order_.push_back(1);
2524          this->getVirtualAxisGroup()->parseChild(node);
2525        }
2526        if (node.getElementName() == scalarName) {
2527          order_.push_back(0);
2528          this->getVirtualScalarGroup()->parseChild(node);
2529        }
2530      } while (node.goToNextElement());
2531      node.goToParentElement();
2532    }
2533
2534    if (!order_.empty())
2535    {
2536      int sizeOrd = order_.size();
2537      axis_domain_order.resize(sizeOrd);
2538      for (int i = 0; i < sizeOrd; ++i)
2539      {
2540        axis_domain_order(i) = order_[i];
2541      }
2542    }
2543
2544    setDomainList();
2545    setAxisList();
2546    setScalarList();
2547   }
2548} // namespace xios
Note: See TracBrowser for help on using the repository browser.