source: XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp @ 1239

Last change on this file since 1239 was 1239, checked in by mhnguyen, 5 years ago

Correcting a minor bug on detecting server reading level

+) Reading server level should be 1 (for now). In the future, maybe level-2 server can be used
+) Correct nbReadSenders with the right ContextClient?

Test
+) On Curie
+) Work with toy

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