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

Last change on this file since 1871 was 1871, 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: 96.7 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      , 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      , 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    CContextClient* client = server->getAssociatedClient();
1668    connectedServerRankRead_ = ranks;
1669    for (int n = 0; n < ranks.size(); n++)
1670    {
1671      int rank = ranks[n];
1672      CBufferIn& buffer = *buffers[n];
1673      buffer >>  isCompressible_; // probably to be removed later
1674      CArray<size_t,1> outIndex;
1675      buffer >> outIndex;
1676      outGlobalIndexFromClient_.insert(std::make_pair(rank, outIndex));
1677      connectedDataSizeRead_[rank] = outIndex.numElements();
1678    }
1679
1680    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize,
1681                                                                                      client->intraComm, ranks);
1682  }
1683  CATCH_DUMP_ATTR
1684 
1685
1686  void CGrid::computeServerDistribution(void)
1687  TRY
1688  {
1689    if (computeServerDistribution_done_) return ;
1690    else computeServerDistribution_done_=true ;
1691
1692    CContext* context = CContext::getCurrent();
1693     
1694    int idx = 0, numElement = axis_domain_order.numElements();
1695    int ssize = numElement;
1696    std::vector<int> indexMap(numElement);
1697    for (int i = 0; i < numElement; ++i)
1698    {
1699      indexMap[i] = idx;
1700      if (2 == axis_domain_order(i))
1701      {
1702        ++ssize;
1703        idx += 2;
1704      }
1705      else
1706        ++idx;
1707    }
1708
1709    for (int n = 0; n < connectedServerRankRead_.size(); n++)
1710    {
1711      int rank = connectedServerRankRead_[n];
1712      size_t dataSize = 0;
1713
1714      if (0 == serverDistribution_)
1715      {
1716        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1717        std::vector<CDomain*> domainList = getDomains();
1718        std::vector<CAxis*> axisList = getAxis();
1719        std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement);
1720        std::vector<CArray<int,1> > globalIndex(numElement);
1721        for (int i = 0; i < numElement; ++i)
1722        {
1723          nGlobElement[i] = globalSize;
1724          if (2 == axis_domain_order(i)) //domain
1725          {
1726            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
1727            nSize[indexMap[i]]  = domainList[domainId]->ni;
1728            nBeginGlobal[indexMap[i]] = 0;
1729            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1730
1731            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
1732            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
1733            nBeginGlobal[indexMap[i] + 1] = 0;
1734            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1735
1736            {
1737              int count = 0;
1738              globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]);
1739              for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx)
1740                for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
1741                {
1742                  globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
1743                  ++count;
1744                }
1745            }
1746
1747            ++domainId;
1748          }
1749          else if (1 == axis_domain_order(i)) // axis
1750          {
1751            nBegin[indexMap[i]] = axisList[axisId]->begin;
1752            nSize[indexMap[i]]  = axisList[axisId]->n;
1753            nBeginGlobal[indexMap[i]] = 0;
1754            nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
1755            globalIndex[i].resize(nSize[indexMap[i]]);
1756            for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
1757              globalIndex[i](idx) = nBegin[indexMap[i]] + idx;
1758
1759            ++axisId;
1760          }
1761          else // scalar
1762          { 
1763            nBegin[indexMap[i]] = 0;
1764            nSize[indexMap[i]]  = 1;
1765            nBeginGlobal[indexMap[i]] = 0;
1766            nGlob[indexMap[i]] = 1;
1767            globalIndex[i].resize(1);
1768            globalIndex[i](0) = 0;
1769            ++scalarId;
1770          }
1771        }
1772        dataSize = 1;
1773
1774        for (int i = 0; i < nSize.size(); ++i)
1775        dataSize *= nSize[i];
1776        serverDistribution_ = new CDistributionServer(context->intraCommRank_, 
1777                                                      globalIndex, axis_domain_order,
1778                                                      nBegin, nSize, nBeginGlobal, nGlob);
1779      }
1780    }
1781  }
1782  CATCH_DUMP_ATTR
1783
1784
1785
1786
1787
1788
1789/* old interface => transform into compute receivedIndex
1790  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers, CContextServer* server)
1791  TRY
1792  {
1793    CContext* context = CContext::getCurrent();
1794    connectedServerRankRead_ = ranks;
1795
1796    nbReadSenders_.clear();
1797    CContextClient* client = server->getAssociatedClient();   
1798     
1799    int idx = 0, numElement = axis_domain_order.numElements();
1800    int ssize = numElement;
1801    std::vector<int> indexMap(numElement);
1802    for (int i = 0; i < numElement; ++i)
1803    {
1804      indexMap[i] = idx;
1805      if (2 == axis_domain_order(i))
1806      {
1807        ++ssize;
1808        idx += 2;
1809      }
1810      else
1811        ++idx;
1812    }
1813
1814    for (int n = 0; n < ranks.size(); n++)
1815    {
1816      int rank = ranks[n];
1817      CBufferIn& buffer = *buffers[n];
1818
1819      buffer >>  isCompressible_;
1820      size_t dataSize = 0;
1821
1822      if (0 == serverDistribution_)
1823      {
1824        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1825        std::vector<CDomain*> domainList = getDomains();
1826        std::vector<CAxis*> axisList = getAxis();
1827        std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement);
1828        std::vector<CArray<int,1> > globalIndex(numElement);
1829        for (int i = 0; i < numElement; ++i)
1830        {
1831          nGlobElement[i] = globalSize;
1832          if (2 == axis_domain_order(i)) //domain
1833          {
1834            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
1835            nSize[indexMap[i]]  = domainList[domainId]->ni;
1836            nBeginGlobal[indexMap[i]] = 0;
1837            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1838
1839            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
1840            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
1841            nBeginGlobal[indexMap[i] + 1] = 0;
1842            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1843
1844            {
1845              int count = 0;
1846              globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]);
1847              for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx)
1848                for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
1849                {
1850                  globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
1851                  ++count;
1852                }
1853            }
1854
1855            ++domainId;
1856          }
1857          else if (1 == axis_domain_order(i)) // axis
1858          {
1859            nBegin[indexMap[i]] = axisList[axisId]->begin;
1860            nSize[indexMap[i]]  = axisList[axisId]->n;
1861            nBeginGlobal[indexMap[i]] = 0;
1862            nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
1863            globalIndex[i].resize(nSize[indexMap[i]]);
1864            for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
1865              globalIndex[i](idx) = nBegin[indexMap[i]] + idx;
1866
1867            ++axisId;
1868          }
1869          else // scalar
1870          {
1871            nBegin[indexMap[i]] = 0;
1872            nSize[indexMap[i]]  = 1;
1873            nBeginGlobal[indexMap[i]] = 0;
1874            nGlob[indexMap[i]] = 1;
1875            globalIndex[i].resize(1);
1876            globalIndex[i](0) = 0;
1877            ++scalarId;
1878          }
1879        }
1880        dataSize = 1;
1881
1882        for (int i = 0; i < nSize.size(); ++i)
1883        dataSize *= nSize[i];
1884        serverDistribution_ = new CDistributionServer(context->intraCommRank_,
1885                                                      globalIndex, axis_domain_order,
1886                                                      nBegin, nSize, nBeginGlobal, nGlob);
1887      }
1888
1889      CArray<size_t,1> outIndex;
1890      buffer >> outIndex;
1891      outGlobalIndexFromClient_.insert(std::make_pair(rank, outIndex));
1892      connectedDataSizeRead_[rank] = outIndex.numElements();
1893
1894      if (doGridHaveDataDistributed(client))
1895      {}
1896      else
1897      {
1898        // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
1899        // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
1900        dataSize = serverDistribution_->getGridSize();
1901      }
1902      writtenDataSize_ += dataSize;
1903    }
1904
1905
1906    // Compute mask of the current grid
1907    {
1908      int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1909      std::vector<CDomain*> domainList = getDomains();
1910      std::vector<CAxis*> axisList = getAxis();
1911      int dimSize = 2 * domainList.size() + axisList.size();
1912      std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize);       
1913      for (int i = 0; i < numElement; ++i)
1914      {         
1915        if (2 == axis_domain_order(i)) //domain
1916        {
1917          nBegin[indexMap[i]] = domainList[domainId]->ibegin;
1918          nSize[indexMap[i]]  = domainList[domainId]->ni;
1919          nBeginGlobal[indexMap[i]] = 0;             
1920          nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1921
1922          nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
1923          nSize[indexMap[i] + 1] = domainList[domainId]->nj;
1924          nBeginGlobal[indexMap[i] + 1] = 0;             
1925          nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1926          ++domainId;
1927        }
1928        else if (1 == axis_domain_order(i)) // axis
1929        {
1930          nBegin[indexMap[i]] = axisList[axisId]->begin;
1931          nSize[indexMap[i]]  = axisList[axisId]->n;
1932          nBeginGlobal[indexMap[i]] = 0;             
1933          nGlob[indexMap[i]] = axisList[axisId]->n_glo;             
1934          ++axisId;
1935        }
1936        else // scalar
1937        { 
1938        }
1939      }
1940     
1941      if (nSize.empty()) // Scalar grid
1942      {
1943        nBegin.push_back(0);
1944        nSize.push_back(1);
1945        nBeginGlobal.push_back(0);             
1946        nGlob.push_back(1); 
1947      }
1948    }
1949
1950    if (isScalarGrid()) return;
1951
1952    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize,
1953                                                                                      client->intraComm, ranks);
1954
1955  }
1956  CATCH_DUMP_ATTR
1957*/
1958
1959
1960  /*
1961     Compute on the fly the global dimension of a grid with its elements
1962     \param[in/out] globalDim global dimension of grid
1963     \param[in] domains list of its domains
1964     \param[in] axiss list of its axis
1965     \param[in] scalars list of its scalars
1966     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1967     \return The dimension of which we do distribution (often for server)
1968  */
1969  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1970                                        const std::vector<CDomain*> domains,
1971                                        const std::vector<CAxis*> axis,
1972                                        const std::vector<CScalar*> scalars,
1973                                        const CArray<int,1>& axisDomainOrder)
1974  TRY
1975 {
1976 //   globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1977    globalDim.resize(domains.size()*2+axis.size());
1978    int positionDimensionDistributed = 1;
1979    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1980    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1981    {
1982      if (2 == axisDomainOrder(i))
1983      {
1984        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1985        {
1986          positionDimensionDistributed = idx;
1987        }
1988        else
1989        {
1990          positionDimensionDistributed = idx +1;
1991        }
1992
1993        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
1994        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
1995
1996        ++idxDomain;
1997        idx += 2;
1998      }
1999      else if (1 == axisDomainOrder(i))
2000      {
2001        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
2002        ++idxAxis;
2003        ++idx;
2004      }
2005      else
2006      {
2007//        globalDim[idx] = 1;
2008        ++idxScalar;
2009//        ++idx;
2010      }
2011    }
2012
2013    return positionDimensionDistributed;
2014  }
2015  CATCH_DUMP_ATTR
2016
2017  // Retrieve the global dimension of grid
2018  std::vector<int> CGrid::getGlobalDimension()
2019  TRY
2020  {
2021    std::vector<int> globalDim;
2022    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
2023
2024    return globalDim;
2025  }
2026  CATCH_DUMP_ATTR
2027
2028  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
2029  int CGrid::getDistributedDimension()
2030  TRY
2031  {
2032    std::vector<int> globalDim;
2033    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
2034  }
2035  CATCH_DUMP_ATTR
2036
2037  bool CGrid::isScalarGrid() const
2038  TRY
2039  {
2040    return (axisList_.empty() && domList_.empty());
2041  }
2042  CATCH
2043
2044  /*!
2045    Verify whether one server need to write data
2046    There are some cases on which one server has nodata to write. For example, when we
2047    just only want to zoom on a domain.
2048  */
2049  bool CGrid::doGridHaveDataToWrite()
2050  TRY
2051  {
2052     return (0 != getWrittenDataSize());
2053  }
2054  CATCH_DUMP_ATTR
2055
2056  /*!
2057    Return size of data which is written on each server
2058    Whatever dimension of a grid, data which are written on server must be presented as
2059    an one dimension array.
2060    \return size of data written on server
2061  */
2062  size_t CGrid::getWrittenDataSize() 
2063  TRY
2064  {
2065    return getServerDistribution()->getGridSize();
2066  }
2067  CATCH
2068
2069  /*!
2070    Returns the number of indexes written by each server.
2071    \return the number of indexes written by each server
2072  */
2073  int CGrid::getNumberWrittenIndexes() const
2074  TRY
2075  {
2076    return numberWrittenIndexes_;
2077  }
2078  CATCH
2079
2080  /*!
2081    Returns the total number of indexes written by the servers.
2082    \return the total number of indexes written by the servers
2083  */
2084  int CGrid::getTotalNumberWrittenIndexes() const
2085  TRY
2086  {
2087    return totalNumberWrittenIndexes_;
2088  }
2089  CATCH
2090
2091  /*!
2092    Returns the offset of indexes written by each server.
2093    \return the offset of indexes written by each server
2094  */
2095  int CGrid::getOffsetWrittenIndexes() const
2096  TRY
2097  {
2098    return offsetWrittenIndexes_;
2099  }
2100  CATCH
2101
2102 
2103  CDistributionClient* CGrid::getClientDistribution()
2104  TRY
2105  {
2106    if (!computeClientDistribution_done_) computeClientDistribution() ;
2107    return clientDistribution_;
2108  }
2109  CATCH_DUMP_ATTR
2110
2111  bool CGrid::doGridHaveDataDistributed(CContextClient* client)
2112  TRY
2113  {
2114    // This function is now useless because it will return false only if server and client size are equal to 1
2115    // to be seriously check in future
2116
2117    if (isScalarGrid()) return false;
2118    else if (0 != client)
2119    {
2120      return  (isDataDistributed() ||  (1 != client->clientSize) || (1 != client->serverSize));
2121    }
2122    else
2123      return isDataDistributed();   
2124  }
2125  CATCH_DUMP_ATTR
2126
2127   /*!
2128   \brief Dispatch event received from client
2129      Whenever a message is received in buffer of server, it will be processed depending on
2130   its event type. A new event type should be added in the switch list to make sure
2131   it processed on server side.
2132   \param [in] event: Received message
2133   */
2134  bool CGrid::dispatchEvent(CEventServer& event)
2135  TRY
2136  {
2137
2138    if (SuperClass::dispatchEvent(event)) return true;
2139    else
2140    {
2141      switch(event.type)
2142      {
2143        case EVENT_ID_INDEX :
2144          recvIndex(event);
2145          return true;
2146          break;
2147
2148         case EVENT_ID_ADD_DOMAIN :
2149           recvAddDomain(event);
2150           return true;
2151           break;
2152
2153         case EVENT_ID_ADD_AXIS :
2154           recvAddAxis(event);
2155           return true;
2156           break;
2157
2158         case EVENT_ID_ADD_SCALAR :
2159           recvAddScalar(event);
2160           return true;
2161           break;
2162        default :
2163          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
2164                << "Unknown Event");
2165          return false;
2166      }
2167    }
2168  }
2169  CATCH
2170
2171   ///---------------------------------------------------------------
2172
2173   CDomain* CGrid::addDomain(const std::string& id)
2174   TRY
2175   {
2176     order_.push_back(2);
2177     axis_domain_order.resize(order_.size());
2178     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
2179     return vDomainGroup_->createChild(id);
2180   }
2181   CATCH_DUMP_ATTR
2182
2183   CAxis* CGrid::addAxis(const std::string& id)
2184   TRY
2185   {
2186     order_.push_back(1);
2187     axis_domain_order.resize(order_.size());
2188     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
2189     return vAxisGroup_->createChild(id);
2190   }
2191   CATCH_DUMP_ATTR
2192
2193   CScalar* CGrid::addScalar(const std::string& id)
2194   TRY
2195   {
2196     order_.push_back(0);
2197     axis_domain_order.resize(order_.size());
2198     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
2199     return vScalarGroup_->createChild(id);
2200   }
2201   CATCH_DUMP_ATTR
2202
2203   //! Change virtual field group to a new one
2204   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
2205   TRY
2206   {
2207      this->vDomainGroup_ = newVDomainGroup;
2208   }
2209   CATCH_DUMP_ATTR
2210
2211   //! Change virtual variable group to new one
2212   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
2213   TRY
2214   {
2215      this->vAxisGroup_ = newVAxisGroup;
2216   }
2217   CATCH_DUMP_ATTR
2218
2219   //! Change virtual variable group to new one
2220   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
2221   TRY
2222   {
2223      this->vScalarGroup_ = newVScalarGroup;
2224   }
2225   CATCH_DUMP_ATTR
2226
2227
2228  void CGrid::sendGridToFileServer(CContextClient* client)
2229  {
2230    if (sendGridToFileServer_done_.count(client)!=0) return ;
2231    else sendGridToFileServer_done_.insert(client) ;
2232
2233    StdString gridDefRoot("grid_definition");
2234    CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
2235    gridPtr->sendCreateChild(this->getId(),client);
2236    this->sendAllAttributesToServer(client);
2237    if (isScalarGrid())  sendIndexScalarGrid();
2238    else  sendIndex();
2239    this->sendAllDomains(client);
2240    this->sendAllAxis(client);
2241    this->sendAllScalars(client);
2242  }
2243
2244   /*!
2245   \brief Send a message to create a domain on server side
2246   \param[in] id String identity of domain that will be created on server
2247   */
2248   void CGrid::sendAddDomain(const string& id, CContextClient* contextClient)
2249   TRY
2250  {
2251      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN, contextClient);
2252   }
2253   CATCH_DUMP_ATTR
2254
2255   /*!
2256   \brief Send a message to create an axis on server side
2257   \param[in] id String identity of axis that will be created on server
2258   */
2259   void CGrid::sendAddAxis(const string& id, CContextClient* contextClient)
2260   TRY
2261   {
2262      sendAddItem(id, (int)EVENT_ID_ADD_AXIS, contextClient);
2263   }
2264   CATCH_DUMP_ATTR
2265
2266   /*!
2267   \brief Send a message to create a scalar on server side
2268   \param[in] id String identity of scalar that will be created on server
2269   */
2270   void CGrid::sendAddScalar(const string& id, CContextClient* contextClient)
2271   TRY
2272   {
2273      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR, contextClient);
2274   }
2275   CATCH_DUMP_ATTR
2276
2277   /*!
2278   \brief Receive a message annoucing the creation of a domain on server side
2279   \param[in] event Received event
2280   */
2281   void CGrid::recvAddDomain(CEventServer& event)
2282   TRY
2283   {
2284
2285      CBufferIn* buffer = event.subEvents.begin()->buffer;
2286      string id;
2287      *buffer >> id;
2288      get(id)->recvAddDomain(*buffer);
2289   }
2290   CATCH
2291
2292   /*!
2293   \brief Receive a message annoucing the creation of a domain on server side
2294   \param[in] buffer Buffer containing message
2295   */
2296   void CGrid::recvAddDomain(CBufferIn& buffer)
2297   TRY
2298   {
2299      string id;
2300      buffer >> id;
2301      addDomain(id);
2302   }
2303   CATCH_DUMP_ATTR
2304
2305   /*!
2306   \brief Receive a message annoucing the creation of an axis on server side
2307   \param[in] event Received event
2308   */
2309   void CGrid::recvAddAxis(CEventServer& event)
2310   TRY
2311   {
2312
2313      CBufferIn* buffer = event.subEvents.begin()->buffer;
2314      string id;
2315      *buffer >> id;
2316      get(id)->recvAddAxis(*buffer);
2317   }
2318   CATCH
2319
2320   /*!
2321   \brief Receive a message annoucing the creation of an axis on server side
2322   \param[in] buffer Buffer containing message
2323   */
2324   void CGrid::recvAddAxis(CBufferIn& buffer)
2325   TRY
2326   {
2327      string id;
2328      buffer >> id;
2329      addAxis(id);
2330   }
2331   CATCH_DUMP_ATTR
2332
2333   /*!
2334   \brief Receive a message annoucing the creation of an scalar on server side
2335   \param[in] event Received event
2336   */
2337   void CGrid::recvAddScalar(CEventServer& event)
2338   TRY
2339   {
2340
2341      CBufferIn* buffer = event.subEvents.begin()->buffer;
2342      string id;
2343      *buffer >> id;
2344      get(id)->recvAddScalar(*buffer);
2345   }
2346   CATCH
2347
2348   /*!
2349   \brief Receive a message annoucing the creation of an scalar on server side
2350   \param[in] buffer Buffer containing message
2351   */
2352   void CGrid::recvAddScalar(CBufferIn& buffer)
2353   TRY
2354   {
2355      string id;
2356      buffer >> id;
2357      addScalar(id);
2358   }
2359   CATCH_DUMP_ATTR
2360
2361  /*!
2362  \brief Check if all elements of the grid are complete
2363  Before make any grid processing, we must be sure that all grid information elements have
2364  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
2365  other context (coupling)
2366  */
2367  bool CGrid::checkIfCompleted(void)
2368  {
2369    setDomainList();
2370    for (auto domainId : domList_) if (!CDomain::get(domainId)->checkIfCompleted()) return false ;
2371    setAxisList() ;
2372    for (auto axisId : axisList_) if (!CAxis::get(axisId)->checkIfCompleted()) return false ;
2373    setScalarList() ;
2374    for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->checkIfCompleted()) return false ;
2375    return true ;
2376  }
2377
2378  /*!
2379  \brief Solve domain and axis references
2380  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
2381  all attributes from their parents, they should be processed with this function
2382  \param[in] apply inherit all attributes of parents (true)
2383  */
2384  void CGrid::solveElementsRefInheritance(bool apply)
2385  TRY
2386  {
2387    setDomainList();
2388    for (auto domainId : domList_)
2389    {
2390      CDomain* pDom = CDomain::get(domainId);
2391      pDom->solveRefInheritance(apply);
2392      pDom->solveInheritanceTransformation();
2393    }
2394
2395    setAxisList();
2396    for (auto axisId : axisList_)
2397    {
2398      CAxis* pAxis = CAxis::get(axisId);
2399      pAxis->solveRefInheritance(apply);
2400      pAxis->solveInheritanceTransformation();
2401    }
2402
2403    setScalarList();
2404    for (auto scalarId : scalarList_)
2405    {
2406      CScalar* pScalar = CScalar::get(scalarId);
2407      pScalar->solveRefInheritance(apply);
2408      pScalar->solveInheritanceTransformation();
2409    }
2410  }
2411  CATCH_DUMP_ATTR
2412
2413 /*!
2414  \brief check attributes of all elements of the grid
2415  */
2416  void CGrid::checkElementsAttributes(void)
2417  TRY
2418  {
2419    setDomainList();
2420    for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes();
2421
2422    setAxisList();
2423    for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes();
2424   
2425    setScalarList();
2426    for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes();
2427  }
2428  CATCH_DUMP_ATTR
2429
2430  bool CGrid::isTransformed()
2431  TRY
2432  {
2433    return isTransformed_;
2434  }
2435  CATCH_DUMP_ATTR
2436
2437  void CGrid::setTransformed()
2438  TRY
2439  {
2440    isTransformed_ = true;
2441  }
2442  CATCH_DUMP_ATTR
2443
2444  CGridTransformation* CGrid::getTransformations()
2445  TRY
2446  {
2447    return transformations_;
2448  }
2449  CATCH_DUMP_ATTR
2450
2451  void CGrid::addTransGridSource(CGrid* gridSrc)
2452  TRY
2453  {
2454    if (gridSrc_.end() == gridSrc_.find(gridSrc))
2455      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
2456  }
2457  CATCH_DUMP_ATTR
2458
2459  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
2460  TRY
2461  {
2462    return gridSrc_;
2463  }
2464  CATCH_DUMP_ATTR
2465
2466  /*!
2467     Complete all the necessary (and lacking) attributes of a grid
2468     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
2469  */
2470  void CGrid::completeGrid(CGrid* transformGridSrc)
2471  TRY
2472  {
2473    if (nullptr != transformGridSrc)
2474    {
2475      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2476      {
2477        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
2478             << "Two grids have different number of elements. " << std::endl
2479             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2480             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2481      }
2482    }
2483
2484    if (isGenerated()) return;
2485    setGenerated();
2486
2487    CGridGenerate gridGenerate(this, transformGridSrc);
2488    gridGenerate.completeGrid();
2489  }
2490  CATCH_DUMP_ATTR
2491
2492  bool CGrid::isGenerated()
2493  TRY
2494  {
2495    return isGenerated_;
2496  }
2497  CATCH
2498
2499  void CGrid::setGenerated()
2500  TRY
2501  {
2502    isGenerated_ = true;
2503  }
2504  CATCH_DUMP_ATTR
2505
2506  void CGrid::transformGrid(CGrid* transformGridSrc)
2507  TRY
2508  {
2509    if (!transformGridSrc)
2510      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2511            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
2512
2513    if (isTransformed()) return;
2514    setTransformed();
2515    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2516    {
2517      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2518           << "Two grids have different number of elements. " << std::endl
2519           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2520           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2521    }
2522    else
2523    {
2524    }
2525
2526    transformations_ = new CGridTransformation(this, transformGridSrc);
2527    transformations_->computeAll();
2528    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
2529
2530    // Ok, now need to compute index of grid source
2531    transformGridSrc->checkMaskIndex(false);
2532  }
2533  CATCH_DUMP_ATTR
2534
2535
2536
2537
2538  void CGrid::prepareTransformGrid(CGrid* transformGridSrc)
2539  TRY
2540  {
2541    if (prepareTransformGrid_done_) return ;
2542
2543    if (!transformGridSrc)
2544      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2545            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
2546
2547    if (isTransformed()) return;
2548    setTransformed();
2549    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2550    {
2551      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2552           << "Two grids have different number of elements. " << std::endl
2553           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2554           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2555    }
2556    else
2557    {
2558    }
2559
2560    transformations_ = new CGridTransformation(this, transformGridSrc);
2561    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
2562
2563    prepareTransformGrid_done_ = true; 
2564  }
2565  CATCH_DUMP_ATTR
2566
2567
2568  void CGrid::makeTransformGrid(void)
2569  TRY
2570  {
2571    if (makeTransformGrid_done_) return ;
2572    transformations_->computeAll();
2573
2574    makeTransformGrid_done_ = true ; 
2575  }
2576  CATCH_DUMP_ATTR
2577
2578
2579  vector<std::string> CGrid::getAuxInputTransformGrid(void)
2580  TRY
2581  {
2582    if (transformations_ != nullptr) return transformations_->getAuxInputs() ;
2583  }
2584  CATCH_DUMP_ATTR
2585
2586
2587
2588
2589
2590
2591
2592  bool CGrid::hasTransform()
2593  TRY
2594  {
2595    if (hasTransform_) return hasTransform_;
2596
2597    std::vector<CDomain*> domList = getDomains();
2598    std::vector<CAxis*> axisList = getAxis();
2599    std::vector<CScalar*> scalarList = getScalars();
2600
2601    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
2602    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
2603    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
2604
2605    return hasTransform_;
2606  }
2607  CATCH_DUMP_ATTR
2608
2609  /*!
2610  \brief Get the list of domain pointers
2611  \return list of domain pointers
2612  */
2613  std::vector<CDomain*> CGrid::getDomains()
2614  TRY
2615  {
2616    std::vector<CDomain*> domList;
2617    if (!domList_.empty())
2618    {
2619      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
2620    }
2621    return domList;
2622  }
2623  CATCH_DUMP_ATTR
2624
2625  /*!
2626  \brief Get the list of  axis pointers
2627  \return list of axis pointers
2628  */
2629  std::vector<CAxis*> CGrid::getAxis()
2630  TRY
2631  {
2632    std::vector<CAxis*> aList;
2633    if (!axisList_.empty())
2634      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
2635
2636    return aList;
2637  }
2638  CATCH_DUMP_ATTR
2639
2640  /*!
2641  \brief Get the list of  axis pointers
2642  \return list of axis pointers
2643  */
2644  std::vector<CScalar*> CGrid::getScalars()
2645  TRY
2646  {
2647    std::vector<CScalar*> sList;
2648    if (!scalarList_.empty())
2649      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
2650
2651    return sList;
2652  }
2653  CATCH_DUMP_ATTR
2654
2655  /*!
2656  \brief Get domain pointer with index
2657  \return domain pointer
2658  */
2659  CDomain* CGrid::getDomain(int domainIndex)
2660  TRY
2661  {
2662    std::vector<CDomain*> domainListP = this->getDomains();
2663    if (domainListP.empty())
2664    {
2665      ERROR("CGrid::getDomain(int domainIndex)",
2666            << "No domain associated to this grid. " << std::endl
2667            << "Grid id = " << this->getId());
2668    }
2669
2670    if (domainIndex >= domainListP.size() || (domainIndex < 0))
2671      ERROR("CGrid::getDomain(int domainIndex)",
2672            << "Domain with the index doesn't exist " << std::endl
2673            << "Grid id = " << this->getId() << std::endl
2674            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
2675
2676    return domainListP[domainIndex];
2677  }
2678  CATCH_DUMP_ATTR
2679
2680  /*!
2681  \brief Get the axis pointer with index
2682  \return axis pointer
2683  */
2684  CAxis* CGrid::getAxis(int axisIndex)
2685  TRY
2686  {
2687    std::vector<CAxis*> axisListP = this->getAxis();
2688    if (axisListP.empty())
2689    {
2690      ERROR("CGrid::getDomain(int axisIndex)",
2691            << "No axis associated to this grid. " << std::endl
2692            << "Grid id = " << this->getId());
2693    }
2694
2695    if (axisIndex >= axisListP.size() || (axisIndex < 0))
2696      ERROR("CGrid::getDomain(int axisIndex)",
2697            << "Domain with the index doesn't exist " << std::endl
2698            << "Grid id = " << this->getId() << std::endl
2699            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
2700
2701    return axisListP[axisIndex];
2702  }
2703  CATCH_DUMP_ATTR
2704
2705  /*!
2706  \brief Get the a scalar pointer
2707  \return scalar pointer
2708  */
2709  CScalar* CGrid::getScalar(int scalarIndex)
2710  TRY
2711  {
2712    std::vector<CScalar*> scalarListP = this->getScalars();
2713    if (scalarListP.empty())
2714    {
2715      ERROR("CGrid::getScalar(int scalarIndex)",
2716            << "No scalar associated to this grid. " << std::endl
2717            << "Grid id = " << this->getId());
2718    }
2719
2720    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
2721      ERROR("CGrid::getScalar(int scalarIndex)",
2722            << "Scalar with the index doesn't exist " << std::endl
2723            << "Grid id = " << this->getId() << std::endl
2724            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
2725
2726    return scalarListP[scalarIndex];
2727  }
2728  CATCH_DUMP_ATTR
2729
2730  /*!
2731  \brief Set domain(s) of a grid from a list
2732  \param[in] domains list of domains
2733  */
2734  void CGrid::setDomainList(const std::vector<CDomain*> domains)
2735  TRY
2736  {
2737    if (isDomListSet) return;
2738    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2739    if (!domains.empty() && domList.empty())
2740    {
2741      for (int i = 0; i < domains.size(); ++i)
2742        this->getVirtualDomainGroup()->addChild(domains[i]);
2743      domList = this->getVirtualDomainGroup()->getAllChildren();
2744    }
2745
2746    if (!domList.empty())
2747    {
2748      int sizeDom = domList.size();
2749      domList_.resize(sizeDom);
2750      for (int i = 0; i < sizeDom; ++i)
2751      {
2752        domList_[i] = domList[i]->getId();
2753      }
2754      isDomListSet = true;
2755    }
2756  }
2757  CATCH_DUMP_ATTR
2758
2759  /*!
2760  \brief Set axis(s) of a grid from a list
2761  \param[in] axis list of axis
2762  */
2763  void CGrid::setAxisList(const std::vector<CAxis*> axis)
2764  TRY
2765  {
2766    if (isAxisListSet) return;
2767    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2768    if (!axis.empty() && aList.empty())
2769    {
2770      for (int i = 0; i < axis.size(); ++i)
2771        this->getVirtualAxisGroup()->addChild(axis[i]);
2772      aList = this->getVirtualAxisGroup()->getAllChildren();
2773    }
2774
2775    if (!aList.empty())
2776    {
2777      int sizeAxis = aList.size();
2778      axisList_.resize(sizeAxis);
2779      for (int i = 0; i < sizeAxis; ++i)
2780      {
2781        axisList_[i] = aList[i]->getId();
2782      }
2783      isAxisListSet = true;
2784    }
2785  }
2786  CATCH_DUMP_ATTR
2787
2788  /*!
2789  \brief Set scalar(s) of a grid from a list
2790  \param[in] scalars list of scalars
2791  */
2792  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
2793  TRY
2794  {
2795    if (isScalarListSet) return;
2796    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2797    if (!scalars.empty() && sList.empty())
2798    {
2799      for (int i = 0; i < scalars.size(); ++i)
2800        this->getVirtualScalarGroup()->addChild(scalars[i]);
2801      sList = this->getVirtualScalarGroup()->getAllChildren();
2802    }
2803
2804    if (!sList.empty())
2805    {
2806      int sizeScalar = sList.size();
2807      scalarList_.resize(sizeScalar);
2808      for (int i = 0; i < sizeScalar; ++i)
2809      {
2810        scalarList_[i] = sList[i]->getId();
2811      }
2812      isScalarListSet = true;
2813    }
2814  }
2815  CATCH_DUMP_ATTR
2816
2817  /*!
2818  \brief Get list of id of domains
2819  \return id list of domains
2820  */
2821  std::vector<StdString> CGrid::getDomainList()
2822  TRY
2823  {
2824    setDomainList();
2825    return domList_;
2826  }
2827  CATCH
2828
2829  /*!
2830  \brief Get list of id of axis
2831  \return id list of axis
2832  */
2833  std::vector<StdString> CGrid::getAxisList()
2834  TRY
2835  {
2836    setAxisList();
2837    return axisList_;
2838  }
2839  CATCH
2840
2841  /*!
2842  \brief Get list of id of scalar
2843  \return id list of scalar
2844  */
2845  std::vector<StdString> CGrid::getScalarList()
2846  TRY
2847  {
2848    setScalarList();
2849    return scalarList_;
2850  }
2851  CATCH
2852
2853  /*!
2854    Send all attributes of domains from client to server
2855  */
2856  void CGrid::sendAllDomains(CContextClient* contextClient)
2857  TRY
2858  {
2859    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2860    for (auto domain : domList)
2861    {
2862      sendAddDomain(domain->getId(),contextClient);
2863      domain->sendDomainToFileServer(contextClient);
2864    }
2865  }
2866  CATCH_DUMP_ATTR
2867
2868  /*!
2869    Send all attributes of axis from client to server
2870  */
2871  void CGrid::sendAllAxis(CContextClient* contextClient)
2872  TRY
2873  {
2874    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2875    for (int i=0; i<aList.size() ; ++i)
2876    {
2877      sendAddAxis(aList[i]->getId(),contextClient);
2878      aList[i]->sendAxisToFileServer(contextClient, getGlobalDimension(), getAxisPositionInGrid()[i]);
2879    }
2880  }
2881  CATCH_DUMP_ATTR
2882
2883  /*!
2884    Send all attributes of scalars from client to server
2885  */
2886  void CGrid::sendAllScalars(CContextClient* contextClient)
2887  TRY
2888  {
2889    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2890    for (auto scalar : sList)
2891    {
2892      sendAddScalar(scalar->getId(),contextClient);
2893      scalar->sendScalarToFileServer(contextClient);
2894    }
2895  }
2896  CATCH_DUMP_ATTR
2897
2898  void CGrid::setContextClient(CContextClient* contextClient)
2899  TRY
2900  {
2901    if (clientsSet.find(contextClient)==clientsSet.end())
2902    {
2903      clients.push_back(contextClient) ;
2904      clientsSet.insert(contextClient);
2905    }
2906    for (int i=0; i<this->getDomains().size(); i++)
2907        this->getDomains()[i]->setContextClient(contextClient);
2908    for (int i=0; i<this->getAxis().size(); i++)
2909        this->getAxis()[i]->setContextClient(contextClient);
2910  }
2911  CATCH_DUMP_ATTR
2912
2913  /*!
2914    Parse a grid, for now, it contains only domain, axis and scalar
2915  */
2916  void CGrid::parse(xml::CXMLNode& node)
2917  TRY
2918  {
2919    SuperClass::parse(node);
2920
2921    if (node.goToChildElement())
2922    {
2923      StdString domainName("domain");
2924      StdString axisName("axis");
2925      StdString scalarName("scalar");
2926      do
2927      {
2928        if (node.getElementName() == domainName) {
2929          order_.push_back(2);
2930          this->getVirtualDomainGroup()->parseChild(node);
2931        }
2932        if (node.getElementName() == axisName) {
2933          order_.push_back(1);
2934          this->getVirtualAxisGroup()->parseChild(node);
2935        }
2936        if (node.getElementName() == scalarName) {
2937          order_.push_back(0);
2938          this->getVirtualScalarGroup()->parseChild(node);
2939        }
2940      } while (node.goToNextElement());
2941      node.goToParentElement();
2942    }
2943
2944    if (!order_.empty())
2945    {
2946      int sizeOrd = order_.size();
2947      axis_domain_order.resize(sizeOrd);
2948      for (int i = 0; i < sizeOrd; ++i)
2949      {
2950        axis_domain_order(i) = order_[i];
2951      }
2952    }
2953
2954    setDomainList();
2955    setAxisList();
2956    setScalarList();
2957   }
2958  CATCH_DUMP_ATTR
2959
2960} // namespace xios
Note: See TracBrowser for help on using the repository browser.