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

Last change on this file since 2034 was 2034, checked in by oabramkina, 22 months ago

Adding a possibility of tiled and non-tiled sent on the same domain.

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