source: XIOS/dev/dev_olga/src/node/grid.cpp @ 1589

Last change on this file since 1589 was 1589, checked in by oabramkina, 5 years ago

Backporting r1578 and r1586 to dev, cleaning the code before merging it to XIOS 2.5.

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