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

Last change on this file since 1869 was 1869, checked in by ymipsl, 19 months ago

Some update...

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