source: XIOS/trunk/src/node/grid.cpp @ 926

Last change on this file since 926 was 926, checked in by rlacroix, 5 years ago

Fix: Make sure that the connected servers are properly set for non-distributed grids.

This could cause the buffers not to be correctly allocated. However this was unlikely to cause any real issues since XIOS tries to recover when an unexpected buffer is requested.

  • 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: 63.9 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20
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      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
34      , transformations_(0), isTransformed_(false)
35      , axisPositionInGrid_(), positionDimensionDistributed_(1), hasDomainAxisBaseRef_(false)
36      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
37   {
38     setVirtualDomainGroup();
39     setVirtualAxisGroup();
40     setVirtualScalarGroup();
41   }
42
43   CGrid::CGrid(const StdString& id)
44      : CObjectTemplate<CGrid>(id), CGridAttributes()
45      , isChecked(false), isDomainAxisChecked(false)
46      , vDomainGroup_(), domList_(), isDomListSet(false)
47      , vAxisGroup_(), axisList_(), isAxisListSet(false)
48      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
49      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
50      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
51      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
52      , transformations_(0), isTransformed_(false)
53      , axisPositionInGrid_(), positionDimensionDistributed_(1), hasDomainAxisBaseRef_(false)
54      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
55   {
56     setVirtualDomainGroup();
57     setVirtualAxisGroup();
58     setVirtualScalarGroup();
59   }
60
61   CGrid::~CGrid(void)
62   {
63    if (0 != clientDistribution_) delete clientDistribution_;
64    if (0 != serverDistribution_) delete serverDistribution_;
65    if (0 != clientServerMap_) delete clientServerMap_;
66    if (0 != transformations_) delete transformations_;
67   }
68
69   ///---------------------------------------------------------------
70
71   StdString CGrid::GetName(void)    { return StdString("grid"); }
72   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
73   ENodeType CGrid::GetType(void)    { return eGrid; }
74
75
76   StdSize CGrid::getDimension(void) const
77   {
78      return globalDim_.size();
79   }
80
81   //---------------------------------------------------------------
82
83   StdSize CGrid::getDataSize(void) const
84   {
85     StdSize retvalue = 1;
86     if (!isScalarGrid())
87     {
88       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
89       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];
90     }
91     return retvalue;
92   }
93
94   /*!
95    * Compute the minimum buffer size required to send the attributes to the server(s).
96    *
97    * \return A map associating the server rank with its minimum buffer size.
98    */
99   std::map<int, StdSize> CGrid::getAttributesBufferSize()
100   {
101     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
102
103     // The grid indexes require a similar size as the actual data
104     std::map<int, StdSize> dataSizes = getDataBufferSize();
105     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
106     for (it = dataSizes.begin(); it != itE; ++it)
107     {
108       it->second += 2 * sizeof(bool);
109       if (it->second > attributesSizes[it->first])
110         attributesSizes[it->first] = it->second;
111     }
112
113     // Account for the axis attributes
114     std::vector<CAxis*> axisList = getAxis();
115     for (size_t i = 0; i < axisList.size(); ++i)
116     {
117       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize();
118       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
119       {
120         if (it->second > attributesSizes[it->first])
121           attributesSizes[it->first] = it->second;
122       }
123     }
124
125     // Account for the domain attributes
126     std::vector<CDomain*> domList = getDomains();
127     for (size_t i = 0; i < domList.size(); ++i)
128     {
129       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize();
130       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
131       {
132         if (it->second > attributesSizes[it->first])
133           attributesSizes[it->first] = it->second;
134       }
135     }
136
137     return attributesSizes;
138   }
139
140   /*!
141    * Compute the minimum buffer size required to send the data to the server(s).
142    *
143    * \param id the id used to tag the data
144    * \return A map associating the server rank with its minimum buffer size.
145    */
146   std::map<int, StdSize> CGrid::getDataBufferSize(const std::string& id /*= ""*/)
147   {
148     std::map<int, StdSize> dataSizes;
149     // The record index is sometimes sent along with the data but we always
150     // include it in the size calculation for the sake of simplicity
151     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() + 2 * sizeof(size_t);
152
153     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_.end();
154     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
155     {
156       int rank = connectedServerRank_[k];
157       std::map<int, size_t>::const_iterator it = connectedDataSize_.find(rank);
158       size_t count = (it != itEnd) ? it->second : 0;
159
160       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
161     }
162
163     return dataSizes;
164   }
165
166   void CGrid::checkAttributesAfterTransformation()
167   {
168     setDomainList();
169     std::vector<CDomain*> domListP = this->getDomains();
170     if (!domListP.empty())
171     {
172       for (int i = 0; i < domListP.size(); ++i)
173       {
174         domListP[i]->checkAttributesOnClientAfterTransformation();
175       }
176     }
177   }
178
179   //---------------------------------------------------------------
180
181   /*!
182    * Test whether the data defined on the grid can be outputted in a compressed way.
183    *
184    * \return true if and only if a mask was defined for this grid
185    */
186   bool CGrid::isCompressible(void) const
187   {
188      return isCompressible_;
189   }
190
191   //---------------------------------------------------------------
192
193   void CGrid::addRelFileCompressed(const StdString& filename)
194   {
195      this->relFilesCompressed.insert(filename);
196   }
197
198   bool CGrid::isWrittenCompressed(const StdString& filename) const
199   {
200      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
201   }
202
203   //---------------------------------------------------------------
204
205   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
206   {
207     if (this->isDomainAxisChecked) return;
208
209     this->solveScalarRef(areAttributesChecked);
210     this->solveAxisRef(areAttributesChecked);
211     this->solveDomainRef(areAttributesChecked);
212     computeGridGlobalDimension(getDomains(), getAxis(), getScalars(), axis_domain_order);
213     this->isDomainAxisChecked = areAttributesChecked;
214   }
215
216   void CGrid::solveDomainAxisBaseRef()
217   {
218     if (this->hasDomainAxisBaseRef_) return;
219     // Account for the scalar attributes
220     std::vector<CScalar*> scalarList = getScalars();
221     for (size_t i = 0; i < scalarList.size(); ++i)
222     {
223       scalarList[i]->setAttributesReference();
224     }
225
226     // Account for the axis attributes
227     std::vector<CAxis*> axisList = getAxis();
228     for (size_t i = 0; i < axisList.size(); ++i)
229     {
230       axisList[i]->setAttributesReference();
231     }
232
233     // Account for the domain attributes
234     std::vector<CDomain*> domList = getDomains();
235     for (size_t i = 0; i < domList.size(); ++i)
236     {
237       domList[i]->setAttributesReference();
238     }
239
240     this->hasDomainAxisBaseRef_ = true;
241   }
242
243   void CGrid::checkEligibilityForCompressedOutput()
244   {
245     // We don't check if the mask is valid here, just if a mask has been defined at this point.
246     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
247   }
248
249   void CGrid::checkMaskIndex(bool doSendingIndex)
250   {
251     CContext* context = CContext::getCurrent();
252     CContextClient* client=context->client;
253
254     if (isScalarGrid())
255     {
256       if (context->hasClient)
257          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
258
259       if (this->isChecked) return;
260       if (context->hasClient)
261       {
262          this->computeIndexScalarGrid();
263       }
264
265       this->isChecked = true;
266       return;
267     }
268
269     if (context->hasClient)
270      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
271
272     if (this->isChecked) return;
273
274     if (context->hasClient)
275     {
276        this->checkAttributesAfterTransformation();
277        this->checkMask();
278        this->computeIndex();
279     }
280     this->isChecked = true;
281   }
282
283   void CGrid::createMask(void)
284   {
285      using namespace std;
286      std::vector<CDomain*> domainP = this->getDomains();
287      std::vector<CAxis*> axisP = this->getAxis();
288      int dim = domainP.size() * 2 + axisP.size();
289
290      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
291      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
292      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
293      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
294
295      switch (dim) {
296        case 1:
297          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
298          break;
299        case 2:
300          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
301          break;
302        case 3:
303          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
304          break;
305        default:
306          break;
307      }
308   }
309
310   void CGrid::checkMask(void)
311   {
312      using namespace std;
313      std::vector<CDomain*> domainP = this->getDomains();
314      std::vector<CAxis*> axisP = this->getAxis();
315      int dim = domainP.size() * 2 + axisP.size();
316
317      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
318      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
319      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
320      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
321
322      switch (dim) {
323        case 1:
324          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
325          break;
326        case 2:
327          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
328          break;
329        case 3:
330          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
331          break;
332//        case 4:
333//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
334//          break;
335//        case 5:
336//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
337//          break;
338//        case 6:
339//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
340//          break;
341//        case 7:
342//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
343//          break;
344        default:
345          break;
346      }
347   }
348
349   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
350   {
351      using namespace std;
352      std::vector<CDomain*> domainP = this->getDomains();
353      std::vector<CAxis*> axisP = this->getAxis();
354      int dim = domainP.size() * 2 + axisP.size();
355
356      switch (dim) {
357        case 1:
358          modifyGridMask(mask_1d, indexToModify);
359          break;
360        case 2:
361          modifyGridMask(mask_2d, indexToModify);
362          break;
363        case 3:
364          modifyGridMask(mask_3d, indexToModify);
365          break;
366
367        default:
368          break;
369      }
370   }
371
372   //---------------------------------------------------------------
373
374   void CGrid::solveDomainRef(bool sendAtt)
375   {
376      setDomainList();
377      std::vector<CDomain*> domListP = this->getDomains();
378      if (!domListP.empty())
379      {
380        for (int i = 0; i < domListP.size(); ++i)
381        {
382          if (sendAtt) domListP[i]->sendCheckedAttributes();
383          else domListP[i]->checkAttributesOnClient();
384        }
385      }
386   }
387
388   //---------------------------------------------------------------
389
390   void CGrid::solveAxisRef(bool sendAtt)
391   {
392      setAxisList();
393      std::vector<CAxis*> axisListP = this->getAxis();
394      if (!axisListP.empty())
395      {
396        int idx = 0;
397        axisPositionInGrid_.resize(0);
398        for (int i = 0; i < axis_domain_order.numElements(); ++i)
399        {
400          int elementDimension = axis_domain_order(i);
401          if (1 == elementDimension)
402          {
403            axisPositionInGrid_.push_back(idx);
404            ++idx;
405          }
406          else if (2 == elementDimension) idx += 2;
407        }
408
409        for (int i = 0; i < axisListP.size(); ++i)
410        {
411          if (sendAtt)
412            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
413          else
414            axisListP[i]->checkAttributesOnClient();
415        }
416      }
417   }
418
419   //---------------------------------------------------------------
420
421   void CGrid::solveScalarRef(bool sendAtt)
422   {
423      setScalarList();
424      std::vector<CScalar*> scalarListP = this->getScalars();
425      if (!scalarListP.empty())
426      {
427        for (int i = 0; i < scalarListP.size(); ++i)
428        {
429          /*Nothing to do for now */
430//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
431//          else scalarListP[i]->checkAttributesOnClient();
432        }
433      }
434   }
435
436   std::vector<int> CGrid::getAxisPositionInGrid() const
437   {
438     return axisPositionInGrid_;
439   }
440
441   //---------------------------------------------------------------
442
443   /*!
444     Compute the global index of grid to send to server as well as the connected server of the current client.
445     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
446     their global index. We can have a map of global index of grid and local index that each client holds
447     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
448     of the current client.
449   */
450   void CGrid::computeIndex(void)
451   {
452     CContext* context = CContext::getCurrent();
453     CContextClient* client = context->client;
454
455     // First of all, compute distribution on client side
456     clientDistribution_ = new CDistributionClient(client->clientRank, this);
457     // Get local data index on client
458     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
459     int nbStoreIndex = storeIndex_client.numElements();
460     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
461     isDataDistributed_= clientDistribution_->isDataDistributed();
462
463     connectedServerRank_.clear();
464
465     if (!doGridHaveDataDistributed())
466     {
467        if (0 == client->clientRank)
468        {
469          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
470          for (int rank = 0; rank < client->serverSize; ++rank)
471          {
472            connectedServerRank_.push_back(rank);
473            connectedDataSize_[rank] = ssize;
474          }
475        }
476        return;
477     }
478
479     // Compute mapping between client and server
480     std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
481     CServerDistributionDescription serverDistributionDescription(globalDim_, client->serverSize);
482     serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
483                                                                client->clientRank,
484                                                                client->clientSize,
485                                                                axis_domain_order,
486                                                                positionDimensionDistributed_);
487     computeIndexByElement(indexServerOnElement, globalIndexOnServer_);
488
489     const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
490     CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
491     CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
492     itGlobalMap  = itbGlobalMap = globalIndexOnServer_.begin();
493     iteGlobalMap = globalIndexOnServer_.end();
494
495     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
496     {
497       int serverRank = itGlobalMap->first;
498       int indexSize = itGlobalMap->second.size();
499       const std::vector<size_t>& indexVec = itGlobalMap->second;
500       for (int idx = 0; idx < indexSize; ++idx)
501       {
502          itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
503          if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
504          {
505             if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
506               connectedDataSize_[serverRank] = 1;
507             else
508               ++connectedDataSize_[serverRank];
509          }
510       }
511     }
512
513     for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
514       connectedServerRank_.push_back(itGlobalMap->first);
515     }
516
517     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
518   }
519
520   /*!
521      Compute the global of (client) grid to send to server with the global index of each element of grid
522      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
523      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
524      on each element whose size is much smaller than one of whole grid.
525      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
526      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
527   */
528   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
529                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
530   {
531     CContext* context = CContext::getCurrent();
532     CContextClient* client = context->client;
533     int serverSize = client->serverSize;
534     std::vector<CDomain*> domList = getDomains();
535     std::vector<CAxis*> axisList = getAxis();
536
537     // Some pre-calculations of global index on each element of current grid.
538     int nbElement = axis_domain_order.numElements();
539     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
540     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
541     std::vector<size_t> elementNGlobal(nbElement);
542     elementNGlobal[0] = 1;
543     size_t globalSize = 1;
544     for (int idx = 0; idx < nbElement; ++idx)
545     {
546       elementNGlobal[idx] = globalSize;
547       size_t elementSize;
548       size_t elementGlobalSize = 1;
549       if (2 == axis_domain_order(idx)) // This is domain
550       {
551         elementSize = domList[domainIdx]->i_index.numElements();
552         globalIndexElement[idx].resize(elementSize);
553         for (int jdx = 0; jdx < elementSize; ++jdx)
554         {
555           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
556         }
557         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
558         ++domainIdx;
559       }
560       else if (1 == axis_domain_order(idx))  // This is axis
561       {
562         elementSize = axisList[axisIdx]->index.numElements();
563         globalIndexElement[idx].resize(elementSize);
564         for (int jdx = 0; jdx < elementSize; ++jdx)
565         {
566           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
567         }
568         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
569         ++axisIdx;
570       }
571       else  // Of course, this is scalar
572       {
573         globalIndexElement[idx].resize(1);
574         globalIndexElement[idx](0) = 0;
575         elementGlobalSize = 1;
576       }
577       globalSize *= elementGlobalSize;
578     }
579
580     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
581     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
582     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
583     // Number of temporary distributed global index held by each client for each server
584     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
585     CArray<int,1> nbIndexOnServerTmp(serverSize);
586     for (int idx = 0; idx < nbElement; ++idx)
587     {
588       nbIndexOnServer = 0;
589       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
590       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
591       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
592       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
593       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
594       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
595                                                                    ite = globalIndexElementOnServerMap.end(), it;
596       for (it = itb; it != ite; ++it)
597       {
598         const std::vector<int>& tmp = it->second;
599         nbIndexOnServerTmp = 0;
600         for (int i = 0; i < tmp.size(); ++i)
601         {
602           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
603         }
604         nbIndexOnServer += nbIndexOnServerTmp;
605       }
606
607       for (int i = 0; i < serverSize; ++i)
608       {
609         if (0 != nbIndexOnServer(i))
610         {
611           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
612           elementOnServer[idx][i] = true;
613         }
614       }
615
616       nbIndexOnServer = 0;
617       for (it = itb; it != ite; ++it)
618       {
619         const std::vector<int>& tmp = it->second;
620         nbIndexOnServerTmp = 0;
621         for (int i = 0; i < tmp.size(); ++i)
622         {
623           if (0 == nbIndexOnServerTmp(tmp[i]))
624           {
625             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
626             ++nbIndexOnServerTmp(tmp[i]);
627           }
628         }
629         nbIndexOnServer += nbIndexOnServerTmp;
630       }
631     }
632
633    // Determine server which contain global source index
634    std::vector<bool> intersectedProc(serverSize, true);
635    for (int idx = 0; idx < nbElement; ++idx)
636    {
637      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
638                     intersectedProc.begin(), intersectedProc.begin(),
639                     std::logical_and<bool>());
640    }
641
642    std::vector<int> srcRank;
643    for (int idx = 0; idx < serverSize; ++idx)
644    {
645      if (intersectedProc[idx]) srcRank.push_back(idx);
646    }
647
648    // Compute the global index of grid from global index of each element.
649    for (int i = 0; i < srcRank.size(); ++i)
650    {
651      size_t ssize = 1;
652      int rankSrc = srcRank[i];
653      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
654      std::vector<size_t> currentIndex(nbElement,0);
655      for (int idx = 0; idx < nbElement; ++idx)
656      {
657        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
658        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
659      }
660      globalIndexOnServer[rankSrc].resize(ssize);
661
662      std::vector<int> idxLoop(nbElement,0);
663      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
664      size_t idx = 0;
665      while (idx < ssize)
666      {
667        for (int ind = 0; ind < nbElement; ++ind)
668        {
669          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
670          {
671            idxLoop[ind] = 0;
672            ++idxLoop[ind+1];
673          }
674
675          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
676        }
677
678        for (int ind = 0; ind < innnerLoopSize; ++ind)
679        {
680          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
681          size_t globalSrcIndex = 0;
682          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
683          {
684            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
685          }
686          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
687          ++idx;
688          ++idxLoop[0];
689        }
690      }
691    }
692   }
693   //----------------------------------------------------------------
694
695   CGrid* CGrid::createGrid(CDomain* domain)
696   {
697      std::vector<CDomain*> vecDom(1, domain);
698      std::vector<CAxis*> vecAxis;
699
700      return createGrid(vecDom, vecAxis);
701   }
702
703   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
704   {
705      std::vector<CDomain*> vecDom(1, domain);
706      std::vector<CAxis*> vecAxis(1, axis);
707
708      return createGrid(vecDom, vecAxis);
709   }
710
711   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
712                            const CArray<int,1>& axisDomainOrder)
713   {
714     std::vector<CScalar*> vecScalar;
715     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
716   }
717
718   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
719                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
720   {
721     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
722   }
723
724   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
725                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
726   {
727      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
728        ERROR("CGrid* CGrid::createGrid(...)",
729              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
730              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
731
732      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
733      grid->setDomainList(domains);
734      grid->setAxisList(axis);
735      grid->setScalarList(scalars);
736
737      // By default, domains are always the first elements of a grid
738      if (0 == axisDomainOrder.numElements())
739      {
740        int size = domains.size() + axis.size() + scalars.size();
741        int nb = 0;
742        grid->axis_domain_order.resize(size);
743        for (int i = 0; i < size; ++i)
744        {
745          if (i < domains.size()) {
746            grid->axis_domain_order(i) = 2;
747
748          }
749          else if ((scalars.size() < (size-nb)) < size) {
750            grid->axis_domain_order(i) = 1;
751          }
752          else
753            grid->axis_domain_order(i) = 0;
754          ++nb;
755        }
756      }
757      else
758      {
759        grid->axis_domain_order.resize(axisDomainOrder.numElements());
760        grid->axis_domain_order = axisDomainOrder;
761      }
762
763      grid->solveDomainAxisRefInheritance(true);
764
765      return grid;
766   }
767
768   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
769   {
770     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
771     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
772     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
773
774     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
775     {
776       CDomain* domain = CDomain::createDomain();
777       domain->duplicateAttributes(domainSrcTmp[idx]);
778       domain->duplicateTransformation(domainSrcTmp[idx]);
779       domain->solveRefInheritance(true);
780       domain->solveInheritanceTransformation();
781       domainSrc.push_back(domain);
782     }
783
784     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
785     {
786       CAxis* axis = CAxis::createAxis();
787       axis->duplicateAttributes(axisSrcTmp[idx]);
788       axis->duplicateTransformation(axisSrcTmp[idx]);
789       axis->solveRefInheritance(true);
790       axis->solveInheritanceTransformation();
791       axisSrc.push_back(axis);
792     }
793
794     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
795     {
796       CScalar* scalar = CScalar::createScalar();
797       scalar->duplicateAttributes(scalarSrcTmp[idx]);
798       scalar->duplicateTransformation(scalarSrcTmp[idx]);
799       scalar->solveRefInheritance(true);
800       scalar->solveInheritanceTransformation();
801       scalarSrc.push_back(scalar);
802     }
803
804      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
805
806      return grid;
807   }
808
809   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
810                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
811   {
812      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
813        ERROR("CGrid* CGrid::generateId(...)",
814              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
815              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
816
817      std::ostringstream id;
818
819      if (domains.empty() && axis.empty() && !scalars.empty())
820        id << "__scalar_";
821
822      if (0 != (domains.size() + axis.size() + scalars.size()))
823      {
824        id << "__grid";
825
826        if (0 == axisDomainOrder.numElements())
827        {
828          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
829          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
830          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
831        }
832        else
833        {
834          size_t iDomain = 0, iAxis = 0, iScalar = 0;
835          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
836          {
837            if (2 == axisDomainOrder(i))
838              id << "_" << domains[iDomain++]->getId();
839            else if (1 == axisDomainOrder(i))
840              id << "_" << axis[iAxis++]->getId();
841            else
842              id << "_" << scalars[iScalar++]->getId();
843          }
844        }
845
846        id << "__";
847      }
848
849      return id.str();
850   }
851
852   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
853   {
854     StdString idSrc  = gridSrc->getId();
855     StdString idDest = gridDest->getId();
856
857     std::ostringstream id;
858     id << idSrc << "__" << idDest;
859
860     return id.str();
861   }
862
863   //----------------------------------------------------------------
864
865   CDomainGroup* CGrid::getVirtualDomainGroup() const
866   {
867     return this->vDomainGroup_;
868   }
869
870   CAxisGroup* CGrid::getVirtualAxisGroup() const
871   {
872     return this->vAxisGroup_;
873   }
874
875   CScalarGroup* CGrid::getVirtualScalarGroup() const
876   {
877     return this->vScalarGroup_;
878   }
879
880   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
881   {
882     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
883     StdSize numElements = stored.numElements();
884     for (StdSize n = 0; n < numElements; ++n)
885     {
886       field[out_i(n)] = stored(n);
887     }
888   }
889
890   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
891   {
892     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
893     StdSize numElements = stored.numElements();
894     for (StdSize n = 0; n < numElements; ++n)
895     {
896       stored(n) = field[out_i(n)];
897     }
898   }
899
900   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
901   {
902     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
903     StdSize numElements = stored.numElements();
904     for (StdSize n = 0; n < numElements; ++n)
905     {
906       field[out_i(n)] = stored(n);
907     }
908   }
909
910   //----------------------------------------------------------------
911
912   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
913   {
914      const StdSize size = storeIndex_client.numElements();
915
916      stored.resize(size);
917      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
918   }
919
920   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
921   {
922      const StdSize size = storeIndex_client.numElements();
923
924      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
925   }
926
927  void CGrid::computeIndexScalarGrid()
928  {
929    CContext* context = CContext::getCurrent();
930    CContextClient* client=context->client;
931
932    storeIndex_client.resize(1);
933    storeIndex_client(0) = 0;
934
935    connectedServerRank_.clear();
936
937    if (0 == client->clientRank)
938    {
939      for (int rank = 0; rank < client->serverSize; ++rank)
940      {
941        connectedServerRank_.push_back(rank);
942        connectedDataSize_[rank] = 1;
943      }
944    }
945    isDataDistributed_ = false;
946  }
947
948  void CGrid::computeCompressedIndex()
949  {
950    compressedOutIndexFromClient = outIndexFromClient;
951
952    std::map<size_t, size_t> indexes;
953
954    {
955      std::map<int, CArray<size_t,1> >::const_iterator it = compressedOutIndexFromClient.begin();
956      std::map<int, CArray<size_t,1> >::const_iterator itEnd = compressedOutIndexFromClient.end();
957      for (; it != itEnd; ++it)
958      {
959        for (int i = 0; i < it->second.numElements(); ++i)
960          indexes.insert(std::make_pair(it->second(i), 0));
961      }
962    }
963
964    {
965      std::map<size_t, size_t>::iterator it = indexes.begin();
966      std::map<size_t, size_t>::iterator itEnd = indexes.end();
967      for (size_t i = 0; it != itEnd; ++it, ++i)
968        it->second = i;
969    }
970
971    {
972      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
973      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
974      for (; it != itEnd; ++it)
975      {
976        for (int i = 0; i < it->second.numElements(); ++i)
977          it->second(i) = indexes[it->second(i)];
978      }
979    }
980  }
981
982  void CGrid::sendIndexScalarGrid()
983  {
984    CContext* context = CContext::getCurrent();
985    CContextClient* client = context->client;
986
987    CEventClient event(getType(), EVENT_ID_INDEX);
988    list<CMessage> listMsg;
989    list<CArray<size_t,1> > listOutIndex;
990
991    if (0 == client->clientRank)
992    {
993      for (int rank = 0; rank < client->serverSize; ++rank)
994      {
995        int nb = 1;
996        storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(nb)));
997        listOutIndex.push_back(CArray<size_t,1>(nb));
998
999        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
1000        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1001
1002        for (int k = 0; k < nb; ++k)
1003        {
1004          outGlobalIndexOnServer(k) = 0;
1005          outLocalIndexToServer(k)  = 0;
1006        }
1007
1008        listMsg.push_back(CMessage());
1009        listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
1010
1011        event.push(rank, 1, listMsg.back());
1012      }
1013
1014      client->sendEvent(event);
1015    }
1016    else
1017      client->sendEvent(event);
1018  }
1019
1020  void CGrid::sendIndex(void)
1021  {
1022    CContext* context = CContext::getCurrent();
1023    CContextClient* client = context->client;
1024
1025    CEventClient event(getType(), EVENT_ID_INDEX);
1026    int rank;
1027    list<CMessage> listMsg;
1028    list<CArray<size_t,1> > listOutIndex;
1029    const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
1030    CDistributionClient::GlobalLocalDataMap::const_iterator itIndex = globalLocalIndexSendToServer.begin(),
1031                                                           iteIndex = globalLocalIndexSendToServer.end();
1032
1033    if (!doGridHaveDataDistributed())
1034    {
1035      if (0 == client->clientRank)
1036      {
1037        int indexSize = globalLocalIndexSendToServer.size();
1038        CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1039        CArray<int,1> outLocalIndexToServer(indexSize);
1040        for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1041        {
1042          outGlobalIndexOnServer(idx) = itIndex->first;
1043          outLocalIndexToServer(idx) = itIndex->second;
1044        }
1045
1046        for (rank = 0; rank < client->serverSize; ++rank)
1047        {
1048          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1049          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1050
1051          listMsg.push_back(CMessage());
1052          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1053
1054          event.push(rank, 1, listMsg.back());
1055        }
1056
1057        client->sendEvent(event);
1058      }
1059      else
1060        client->sendEvent(event);
1061    }
1062    else
1063    {
1064      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
1065      itGlobalMap = globalIndexOnServer_.begin();
1066      iteGlobalMap = globalIndexOnServer_.end();
1067
1068      std::map<int,std::vector<int> >localIndexTmp;
1069      std::map<int,std::vector<size_t> > globalIndexTmp;
1070      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1071      {
1072        int serverRank = itGlobalMap->first;
1073        int indexSize = itGlobalMap->second.size();
1074        const std::vector<size_t>& indexVec = itGlobalMap->second;
1075        for (int idx = 0; idx < indexSize; ++idx)
1076        {
1077          itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
1078          if (iteIndex != itIndex)
1079          {
1080            globalIndexTmp[serverRank].push_back(itIndex->first);
1081            localIndexTmp[serverRank].push_back(itIndex->second);
1082          }
1083        }
1084      }
1085
1086      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
1087      {
1088        rank = connectedServerRank_[ns];
1089        int nb = 0;
1090        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
1091          nb = globalIndexTmp[rank].size();
1092
1093        storeIndex_toSrv.insert(make_pair(rank, CArray<int,1>(nb)));
1094        listOutIndex.push_back(CArray<size_t,1>(nb));
1095
1096        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
1097        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1098
1099        for (int k = 0; k < nb; ++k)
1100        {
1101          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1102          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1103        }
1104
1105        listMsg.push_back(CMessage());
1106        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1107
1108        event.push(rank, nbSenders[rank], listMsg.back());
1109      }
1110
1111      client->sendEvent(event);
1112    }
1113  }
1114
1115  void CGrid::recvIndex(CEventServer& event)
1116  {
1117    string gridId;
1118    vector<int> ranks;
1119    vector<CBufferIn*> buffers;
1120
1121    list<CEventServer::SSubEvent>::iterator it;
1122    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1123    {
1124      ranks.push_back(it->rank);
1125      CBufferIn* buffer = it->buffer;
1126      *buffer >> gridId;
1127      buffers.push_back(buffer);
1128    }
1129    get(gridId)->recvIndex(ranks, buffers);
1130  }
1131
1132  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
1133                                         const std::vector<CAxis*>& axis,
1134                                         const std::vector<CScalar*>& scalars,
1135                                         const CArray<int,1>& axisDomainOrder)
1136  {
1137    globalDim_.resize(domains.size()*2+axis.size()+scalars.size());
1138    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1139    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1140    {
1141      if (2 == axisDomainOrder(i))
1142      {
1143        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1144        {
1145          positionDimensionDistributed_ = idx;
1146        }
1147        else
1148        {
1149          positionDimensionDistributed_ = idx +1;
1150        }
1151
1152        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
1153        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
1154
1155        ++idxDomain;
1156        idx += 2;
1157      }
1158      else if (1 == axisDomainOrder(i))
1159      {
1160        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
1161        ++idxAxis;
1162        ++idx;
1163      }
1164      else
1165      {
1166        globalDim_[idx] = 1;
1167        ++idxScalar;
1168        ++idx;
1169      }
1170    }
1171  }
1172
1173  std::vector<int> CGrid::getGlobalDimension()
1174  {
1175    return globalDim_;
1176  }
1177
1178  bool CGrid::isScalarGrid() const
1179  {
1180    return (axisList_.empty() && domList_.empty());
1181  }
1182
1183  /*!
1184    Verify whether one server need to write data
1185    There are some cases on which one server has nodata to write. For example, when we
1186    just only want to zoom on a domain.
1187  */
1188  bool CGrid::doGridHaveDataToWrite()
1189  {
1190     return (0 != writtenDataSize_);
1191  }
1192
1193  /*!
1194    Return size of data which is written on each server
1195    Whatever dimension of a grid, data which are written on server must be presented as
1196    an one dimension array.
1197    \return size of data written on server
1198  */
1199  size_t CGrid::getWrittenDataSize() const
1200  {
1201    return writtenDataSize_;
1202  }
1203
1204  /*!
1205    Returns the number of indexes written by each server.
1206    \return the number of indexes written by each server
1207  */
1208  int CGrid::getNumberWrittenIndexes() const
1209  {
1210    return numberWrittenIndexes_;
1211  }
1212
1213  /*!
1214    Returns the total number of indexes written by the servers.
1215    \return the total number of indexes written by the servers
1216  */
1217  int CGrid::getTotalNumberWrittenIndexes() const
1218  {
1219    return totalNumberWrittenIndexes_;
1220  }
1221
1222  /*!
1223    Returns the offset of indexes written by each server.
1224    \return the offset of indexes written by each server
1225  */
1226  int CGrid::getOffsetWrittenIndexes() const
1227  {
1228    return offsetWrittenIndexes_;
1229  }
1230
1231  CDistributionServer* CGrid::getDistributionServer()
1232  {
1233    return serverDistribution_;
1234  }
1235
1236  CDistributionClient* CGrid::getDistributionClient()
1237  {
1238    return clientDistribution_;
1239  }
1240
1241  bool CGrid::doGridHaveDataDistributed()
1242  {
1243    if (isScalarGrid()) return false;
1244    else
1245      return isDataDistributed_;
1246  }
1247
1248  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1249  {
1250    CContext* context = CContext::getCurrent();
1251    CContextServer* server = context->server;
1252    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
1253    connectedServerRank_ = ranks;
1254
1255    for (int n = 0; n < ranks.size(); n++)
1256    {
1257      int rank = ranks[n];
1258      CBufferIn& buffer = *buffers[n];
1259
1260      buffer >> isDataDistributed_ >> isCompressible_;
1261      size_t dataSize = 0;
1262
1263      if (isScalarGrid())
1264      {
1265        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
1266        CArray<size_t,1> outIndex;
1267        buffer >> outIndex;
1268        outIndexFromClient.insert(std::make_pair(rank, outIndex));
1269        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
1270        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1271                                                      nZoomBeginGlobal, nGlob);
1272        return;
1273      }
1274
1275      if (0 == serverDistribution_)
1276      {
1277        int idx = 0, numElement = axis_domain_order.numElements();
1278        int ssize = numElement;
1279        std::vector<int> indexMap(numElement);
1280        for (int i = 0; i < numElement; ++i)
1281        {
1282          indexMap[i] = idx;
1283          if (2 == axis_domain_order(i))
1284          {
1285            ++ssize;
1286            idx += 2;
1287          }
1288          else
1289            ++idx;
1290        }
1291
1292        int axisId = 0, domainId = 0, scalarId = 0;
1293        std::vector<CDomain*> domainList = getDomains();
1294        std::vector<CAxis*> axisList = getAxis();
1295        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
1296        for (int i = 0; i < numElement; ++i)
1297        {
1298          if (2 == axis_domain_order(i)) //domain
1299          {
1300            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
1301            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
1302            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
1303            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1304
1305            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
1306            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
1307            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
1308            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1309            ++domainId;
1310          }
1311          else if (1 == axis_domain_order(i)) // axis
1312          {
1313            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1314            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1315            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
1316            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1317            ++axisId;
1318          }
1319          else // scalar
1320          {
1321            nZoomBegin[indexMap[i]] = 0;
1322            nZoomSize[indexMap[i]]  = 1;
1323            nZoomBeginGlobal[indexMap[i]] = 0;
1324            nGlob[indexMap[i]] = 1;
1325            ++scalarId;
1326          }
1327        }
1328        dataSize = 1;
1329        for (int i = 0; i < nZoomSize.size(); ++i)
1330          dataSize *= nZoomSize[i];
1331
1332        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1333                                                      nZoomBeginGlobal, nGlob);
1334      }
1335
1336      CArray<size_t,1> outIndex;
1337      buffer >> outIndex;
1338      if (isDataDistributed_)
1339        serverDistribution_->computeLocalIndex(outIndex);
1340      else
1341      {
1342        dataSize = outIndex.numElements();
1343        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
1344      }
1345      writtenDataSize_ += dataSize;
1346
1347      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1348      connectedDataSize_[rank] = outIndex.numElements();
1349      numberWrittenIndexes_ += outIndex.numElements();
1350    }
1351
1352    if (isDataDistributed_)
1353    {
1354      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1355      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1356      offsetWrittenIndexes_ -= numberWrittenIndexes_;
1357    }
1358    else
1359      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1360
1361    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1362  }
1363
1364   /*!
1365   \brief Dispatch event received from client
1366      Whenever a message is received in buffer of server, it will be processed depending on
1367   its event type. A new event type should be added in the switch list to make sure
1368   it processed on server side.
1369   \param [in] event: Received message
1370   */
1371  bool CGrid::dispatchEvent(CEventServer& event)
1372  {
1373
1374    if (SuperClass::dispatchEvent(event)) return true;
1375    else
1376    {
1377      switch(event.type)
1378      {
1379        case EVENT_ID_INDEX :
1380          recvIndex(event);
1381          return true;
1382          break;
1383
1384         case EVENT_ID_ADD_DOMAIN :
1385           recvAddDomain(event);
1386           return true;
1387           break;
1388
1389         case EVENT_ID_ADD_AXIS :
1390           recvAddAxis(event);
1391           return true;
1392           break;
1393
1394         case EVENT_ID_ADD_SCALAR :
1395           recvAddScalar(event);
1396           return true;
1397           break;
1398        default :
1399          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1400                << "Unknown Event");
1401          return false;
1402      }
1403    }
1404  }
1405
1406   ///---------------------------------------------------------------
1407
1408   CDomain* CGrid::addDomain(const std::string& id)
1409   {
1410     order_.push_back(2);
1411     axis_domain_order.resize(order_.size());
1412     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1413     return vDomainGroup_->createChild(id);
1414   }
1415
1416   CAxis* CGrid::addAxis(const std::string& id)
1417   {
1418     order_.push_back(1);
1419     axis_domain_order.resize(order_.size());
1420     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1421     return vAxisGroup_->createChild(id);
1422   }
1423
1424   CScalar* CGrid::addScalar(const std::string& id)
1425   {
1426     order_.push_back(0);
1427     axis_domain_order.resize(order_.size());
1428     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1429     return vScalarGroup_->createChild(id);
1430   }
1431
1432   //! Change virtual field group to a new one
1433   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1434   {
1435      this->vDomainGroup_ = newVDomainGroup;
1436   }
1437
1438   //! Change virtual variable group to new one
1439   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1440   {
1441      this->vAxisGroup_ = newVAxisGroup;
1442   }
1443
1444   //! Change virtual variable group to new one
1445   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1446   {
1447      this->vScalarGroup_ = newVScalarGroup;
1448   }
1449
1450   //----------------------------------------------------------------
1451   //! Create virtual field group, which is done normally on initializing file
1452   void CGrid::setVirtualDomainGroup(void)
1453   {
1454      this->setVirtualDomainGroup(CDomainGroup::create());
1455   }
1456
1457   //! Create virtual variable group, which is done normally on initializing file
1458   void CGrid::setVirtualAxisGroup(void)
1459   {
1460      this->setVirtualAxisGroup(CAxisGroup::create());
1461   }
1462
1463   //! Create virtual variable group, which is done normally on initializing file
1464   void CGrid::setVirtualScalarGroup(void)
1465   {
1466      this->setVirtualScalarGroup(CScalarGroup::create());
1467   }
1468
1469   /*!
1470   \brief Send a message to create a domain on server side
1471   \param[in] id String identity of domain that will be created on server
1472   */
1473   void CGrid::sendAddDomain(const string& id)
1474   {
1475    CContext* context=CContext::getCurrent();
1476
1477    if (! context->hasServer )
1478    {
1479       CContextClient* client=context->client;
1480
1481       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1482       if (client->isServerLeader())
1483       {
1484         CMessage msg;
1485         msg<<this->getId();
1486         msg<<id;
1487         const std::list<int>& ranks = client->getRanksServerLeader();
1488         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1489           event.push(*itRank,1,msg);
1490         client->sendEvent(event);
1491       }
1492       else client->sendEvent(event);
1493    }
1494   }
1495
1496   /*!
1497   \brief Send a message to create an axis on server side
1498   \param[in] id String identity of axis that will be created on server
1499   */
1500   void CGrid::sendAddAxis(const string& id)
1501   {
1502    CContext* context=CContext::getCurrent();
1503
1504    if (! context->hasServer )
1505    {
1506       CContextClient* client=context->client;
1507
1508       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1509       if (client->isServerLeader())
1510       {
1511         CMessage msg;
1512         msg<<this->getId();
1513         msg<<id;
1514         const std::list<int>& ranks = client->getRanksServerLeader();
1515         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1516           event.push(*itRank,1,msg);
1517         client->sendEvent(event);
1518       }
1519       else client->sendEvent(event);
1520    }
1521   }
1522
1523   /*!
1524   \brief Send a message to create a scalar on server side
1525   \param[in] id String identity of scalar that will be created on server
1526   */
1527   void CGrid::sendAddScalar(const string& id)
1528   {
1529    CContext* context=CContext::getCurrent();
1530
1531    if (! context->hasServer )
1532    {
1533       CContextClient* client=context->client;
1534
1535       CEventClient event(this->getType(),EVENT_ID_ADD_SCALAR);
1536       if (client->isServerLeader())
1537       {
1538         CMessage msg;
1539         msg<<this->getId();
1540         msg<<id;
1541         const std::list<int>& ranks = client->getRanksServerLeader();
1542         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1543           event.push(*itRank,1,msg);
1544         client->sendEvent(event);
1545       }
1546       else client->sendEvent(event);
1547    }
1548   }
1549
1550   /*!
1551   \brief Receive a message annoucing the creation of a domain on server side
1552   \param[in] event Received event
1553   */
1554   void CGrid::recvAddDomain(CEventServer& event)
1555   {
1556
1557      CBufferIn* buffer = event.subEvents.begin()->buffer;
1558      string id;
1559      *buffer >> id;
1560      get(id)->recvAddDomain(*buffer);
1561   }
1562
1563   /*!
1564   \brief Receive a message annoucing the creation of a domain on server side
1565   \param[in] buffer Buffer containing message
1566   */
1567   void CGrid::recvAddDomain(CBufferIn& buffer)
1568   {
1569      string id;
1570      buffer >> id;
1571      addDomain(id);
1572   }
1573
1574   /*!
1575   \brief Receive a message annoucing the creation of an axis on server side
1576   \param[in] event Received event
1577   */
1578   void CGrid::recvAddAxis(CEventServer& event)
1579   {
1580
1581      CBufferIn* buffer = event.subEvents.begin()->buffer;
1582      string id;
1583      *buffer >> id;
1584      get(id)->recvAddAxis(*buffer);
1585   }
1586
1587   /*!
1588   \brief Receive a message annoucing the creation of an axis on server side
1589   \param[in] buffer Buffer containing message
1590   */
1591   void CGrid::recvAddAxis(CBufferIn& buffer)
1592   {
1593      string id;
1594      buffer >> id;
1595      addAxis(id);
1596   }
1597
1598   /*!
1599   \brief Receive a message annoucing the creation of an scalar on server side
1600   \param[in] event Received event
1601   */
1602   void CGrid::recvAddScalar(CEventServer& event)
1603   {
1604
1605      CBufferIn* buffer = event.subEvents.begin()->buffer;
1606      string id;
1607      *buffer >> id;
1608      get(id)->recvAddScalar(*buffer);
1609   }
1610
1611   /*!
1612   \brief Receive a message annoucing the creation of an scalar on server side
1613   \param[in] buffer Buffer containing message
1614   */
1615   void CGrid::recvAddScalar(CBufferIn& buffer)
1616   {
1617      string id;
1618      buffer >> id;
1619      addScalar(id);
1620   }
1621
1622  /*!
1623  \brief Solve domain and axis references
1624  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1625  all attributes from their parents, they should be processed with this function
1626  \param[in] apply inherit all attributes of parents (true)
1627  */
1628  void CGrid::solveDomainAxisRefInheritance(bool apply)
1629  {
1630    CContext* context = CContext::getCurrent();
1631    unsigned int vecSize, i;
1632    std::vector<StdString>::iterator it, itE;
1633    setDomainList();
1634    it = domList_.begin(); itE = domList_.end();
1635    for (; it != itE; ++it)
1636    {
1637      CDomain* pDom = CDomain::get(*it);
1638      if (context->hasClient)
1639      {
1640        pDom->solveRefInheritance(apply);
1641        pDom->solveInheritanceTransformation();
1642      }
1643    }
1644
1645    setAxisList();
1646    it = axisList_.begin(); itE = axisList_.end();
1647    for (; it != itE; ++it)
1648    {
1649      CAxis* pAxis = CAxis::get(*it);
1650      if (context->hasClient)
1651      {
1652        pAxis->solveRefInheritance(apply);
1653        pAxis->solveInheritanceTransformation();
1654      }
1655    }
1656
1657    setScalarList();
1658    it = scalarList_.begin(); itE = scalarList_.end();
1659    for (; it != itE; ++it)
1660    {
1661      CScalar* pScalar = CScalar::get(*it);
1662      if (context->hasClient)
1663      {
1664        pScalar->solveRefInheritance(apply);
1665        pScalar->solveInheritanceTransformation();
1666      }
1667    }
1668  }
1669
1670  bool CGrid::isTransformed()
1671  {
1672    return isTransformed_;
1673  }
1674
1675  void CGrid::setTransformed()
1676  {
1677    isTransformed_ = true;
1678  }
1679
1680  CGridTransformation* CGrid::getTransformations()
1681  {
1682    return transformations_;
1683  }
1684
1685  void CGrid::addTransGridSource(CGrid* gridSrc)
1686  {
1687    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1688      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1689  }
1690
1691  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1692  {
1693    return gridSrc_;
1694  }
1695
1696  /*!
1697     Complete all the necessary (and lacking) attributes of a grid
1698     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1699  */
1700  void CGrid::completeGrid(CGrid* transformGridSrc)
1701  {
1702    if (0 != transformGridSrc)
1703    {
1704      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1705      {
1706        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1707             << "Two grids have different dimension size"
1708             << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1709             << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1710      }
1711    }
1712
1713    if (isGenerated()) return;
1714    setGenerated();
1715
1716    CGridGenerate gridGenerate(this, transformGridSrc);
1717    gridGenerate.completeGrid();
1718  }
1719
1720  bool CGrid::isGenerated()
1721  {
1722    return isGenerated_;
1723  }
1724
1725  void CGrid::setGenerated()
1726  {
1727    isGenerated_ = true;
1728  }
1729
1730  void CGrid::transformGrid(CGrid* transformGridSrc)
1731  {
1732    if (!transformGridSrc)
1733      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1734            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1735
1736    if (isTransformed()) return;
1737    setTransformed();
1738    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1739    {
1740      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1741           << "Two grids have different dimension size"
1742           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1743           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1744    }
1745    else
1746    {
1747    }
1748
1749    transformations_ = new CGridTransformation(this, transformGridSrc);
1750    transformations_->computeAll();
1751    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1752
1753    // Ok, now need to compute index of grid source
1754    transformGridSrc->checkMaskIndex(false);
1755  }
1756
1757  bool CGrid::hasTransform()
1758  {
1759    if (hasTransform_) return hasTransform_;
1760
1761    std::vector<CDomain*> domList = getDomains();
1762    std::vector<CAxis*> axisList = getAxis();
1763    std::vector<CScalar*> scalarList = getScalars();
1764
1765    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
1766    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
1767    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
1768
1769    return hasTransform_;
1770  }
1771
1772  /*!
1773  \brief Get the list of domain pointers
1774  \return list of domain pointers
1775  */
1776  std::vector<CDomain*> CGrid::getDomains()
1777  {
1778    std::vector<CDomain*> domList;
1779    if (!domList_.empty())
1780    {
1781      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1782    }
1783    return domList;
1784  }
1785
1786  /*!
1787  \brief Get the list of  axis pointers
1788  \return list of axis pointers
1789  */
1790  std::vector<CAxis*> CGrid::getAxis()
1791  {
1792    std::vector<CAxis*> aList;
1793    if (!axisList_.empty())
1794      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1795
1796    return aList;
1797  }
1798
1799  /*!
1800  \brief Get the list of  axis pointers
1801  \return list of axis pointers
1802  */
1803  std::vector<CScalar*> CGrid::getScalars()
1804  {
1805    std::vector<CScalar*> sList;
1806    if (!scalarList_.empty())
1807      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
1808
1809    return sList;
1810  }
1811
1812  /*!
1813  \brief Set domain(s) of a grid from a list
1814  \param[in] domains list of domains
1815  */
1816  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1817  {
1818    if (isDomListSet) return;
1819    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1820    if (!domains.empty() && domList.empty())
1821    {
1822      for (int i = 0; i < domains.size(); ++i)
1823        this->getVirtualDomainGroup()->addChild(domains[i]);
1824      domList = this->getVirtualDomainGroup()->getAllChildren();
1825    }
1826
1827    if (!domList.empty())
1828    {
1829      int sizeDom = domList.size();
1830      domList_.resize(sizeDom);
1831      for (int i = 0; i < sizeDom; ++i)
1832      {
1833        domList_[i] = domList[i]->getId();
1834      }
1835      isDomListSet = true;
1836    }
1837
1838  }
1839
1840  /*!
1841  \brief Set axis(s) of a grid from a list
1842  \param[in] axis list of axis
1843  */
1844  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1845  {
1846    if (isAxisListSet) return;
1847    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1848    if (!axis.empty() && aList.empty())
1849    {
1850      for (int i = 0; i < axis.size(); ++i)
1851        this->getVirtualAxisGroup()->addChild(axis[i]);
1852      aList = this->getVirtualAxisGroup()->getAllChildren();
1853    }
1854
1855    if (!aList.empty())
1856    {
1857      int sizeAxis = aList.size();
1858      axisList_.resize(sizeAxis);
1859      for (int i = 0; i < sizeAxis; ++i)
1860      {
1861        axisList_[i] = aList[i]->getId();
1862      }
1863      isAxisListSet = true;
1864    }
1865  }
1866
1867  /*!
1868  \brief Set scalar(s) of a grid from a list
1869  \param[in] scalars list of scalars
1870  */
1871  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
1872  {
1873    if (isScalarListSet) return;
1874    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
1875    if (!scalars.empty() && sList.empty())
1876    {
1877      for (int i = 0; i < scalars.size(); ++i)
1878        this->getVirtualScalarGroup()->addChild(scalars[i]);
1879      sList = this->getVirtualScalarGroup()->getAllChildren();
1880    }
1881
1882    if (!sList.empty())
1883    {
1884      int sizeScalar = sList.size();
1885      scalarList_.resize(sizeScalar);
1886      for (int i = 0; i < sizeScalar; ++i)
1887      {
1888        scalarList_[i] = sList[i]->getId();
1889      }
1890      isScalarListSet = true;
1891    }
1892  }
1893
1894  /*!
1895  \brief Get list of id of domains
1896  \return id list of domains
1897  */
1898  std::vector<StdString> CGrid::getDomainList()
1899  {
1900    setDomainList();
1901    return domList_;
1902  }
1903
1904  /*!
1905  \brief Get list of id of axis
1906  \return id list of axis
1907  */
1908  std::vector<StdString> CGrid::getAxisList()
1909  {
1910    setAxisList();
1911    return axisList_;
1912  }
1913
1914  /*!
1915  \brief Get list of id of scalar
1916  \return id list of scalar
1917  */
1918  std::vector<StdString> CGrid::getScalarList()
1919  {
1920    setScalarList();
1921    return scalarList_;
1922  }
1923
1924  /*!
1925    Send all attributes of domains from client to server
1926  */
1927  void CGrid::sendAllDomains()
1928  {
1929    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1930    int dSize = domList.size();
1931    for (int i = 0; i < dSize; ++i)
1932    {
1933      sendAddDomain(domList[i]->getId());
1934      domList[i]->sendAllAttributesToServer();
1935    }
1936  }
1937
1938  /*!
1939    Send all attributes of axis from client to server
1940  */
1941  void CGrid::sendAllAxis()
1942  {
1943    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1944    int aSize = aList.size();
1945
1946    for (int i = 0; i < aSize; ++i)
1947    {
1948      sendAddAxis(aList[i]->getId());
1949      aList[i]->sendAllAttributesToServer();
1950    }
1951  }
1952
1953  /*!
1954    Send all attributes of scalars from client to server
1955  */
1956  void CGrid::sendAllScalars()
1957  {
1958    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
1959    int sSize = sList.size();
1960
1961    for (int i = 0; i < sSize; ++i)
1962    {
1963      sendAddScalar(sList[i]->getId());
1964      sList[i]->sendAllAttributesToServer();
1965    }
1966  }
1967
1968  /*!
1969    Parse a grid, for now, it contains only domain, axis and scalar
1970  */
1971  void CGrid::parse(xml::CXMLNode& node)
1972  {
1973    SuperClass::parse(node);
1974
1975    if (node.goToChildElement())
1976    {
1977      StdString domainName("domain");
1978      StdString axisName("axis");
1979      StdString scalarName("scalar");
1980      do
1981      {
1982        if (node.getElementName() == domainName) {
1983          order_.push_back(2);
1984          this->getVirtualDomainGroup()->parseChild(node);
1985        }
1986        if (node.getElementName() == axisName) {
1987          order_.push_back(1);
1988          this->getVirtualAxisGroup()->parseChild(node);
1989        }
1990        if (node.getElementName() == scalarName) {
1991          order_.push_back(0);
1992          this->getVirtualScalarGroup()->parseChild(node);
1993        }
1994      } while (node.goToNextElement());
1995      node.goToParentElement();
1996    }
1997
1998    if (!order_.empty())
1999    {
2000      int sizeOrd = order_.size();
2001      axis_domain_order.resize(sizeOrd);
2002      for (int i = 0; i < sizeOrd; ++i)
2003      {
2004        axis_domain_order(i) = order_[i];
2005      }
2006    }
2007
2008    setDomainList();
2009    setAxisList();
2010    setScalarList();
2011   }
2012} // namespace xios
Note: See TracBrowser for help on using the repository browser.