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

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

Big update on on going work related to data distribution and transfer between clients and servers.

  • move all related file into distribution directorie
  • implement the concept of data "View"
  • implement the concept of "connector" which make the data transfer between 2 differents "Views"

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