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

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

XIOS coupling Branch

  • fix timestamp problem when receiving field from other coupling context
  • fix deadlock : when receiving index from coupling context, a collective communication was involved which is forbiden

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