source: XIOS/dev/dev_olga/src/node/grid.cpp @ 1584

Last change on this file since 1584 was 1584, checked in by oabramkina, 6 years ago

Clean-up in transformation classes related to the new treatment of grid mask at the entrance of a workflow.

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