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

Last change on this file since 1571 was 1571, checked in by oabramkina, 6 years ago

Taking care of cases when a process doesn't possess a grid (its domain or axe size is zero).

Tested with CMIP6 toy models and IPSL model.

To do: remove grid mask from transformations.

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