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

Last change on this file since 1784 was 1784, checked in by ymipsl, 5 years ago
  • Preparing coupling functionalities.
  • Make some cleaner things

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