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

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

XIOS coupling branch
Some updates.

First coupling test is beginning to work...

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