source: XIOS/dev/dev_oa/src/node/grid.cpp @ 1966

Last change on this file since 1966 was 1966, checked in by oabramkina, 2 years ago

dev_oa: first working version for tiled domains

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