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

Last change on this file since 1314 was 1311, checked in by ymipsl, 6 years ago

Fix conflict between for domain mask_1d and mask_2d when inheritance is done after transformation. Now class attribute "domainMask" is fill either by mask_1d or mask_2d and will be used instead of mask_1d in code.
This is a temporary fix which will solve later by reconstructing a cleanear grid graph.

YM

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