source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp @ 1870

Last change on this file since 1870 was 1870, checked in by ymipsl, 4 years ago

Some update on XIOS_COUPLING branch...

YM

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