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

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

Ticket 98: Fixing bug relating to element size

+) Correct return value of size computation for each element of grid

Test
+) On Curie
+) Size returns correctly

  • 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.7 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     if (!doGridHaveDataDistributed())
464     {
465        if (0 == client->clientRank)
466        {
467          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
468          for (int rank = 0; rank < client->serverSize; ++rank)
469            connectedDataSize_[rank] = ssize;
470        }
471        return;
472     }
473
474     // Compute mapping between client and server
475     std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
476     CServerDistributionDescription serverDistributionDescription(globalDim_, client->serverSize);
477     serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
478                                                                client->clientRank,
479                                                                client->clientSize,
480                                                                axis_domain_order,
481                                                                positionDimensionDistributed_);
482     computeIndexByElement(indexServerOnElement, globalIndexOnServer_);
483
484     const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
485     CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
486     CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
487     itGlobalMap  = itbGlobalMap = globalIndexOnServer_.begin();
488     iteGlobalMap = globalIndexOnServer_.end();
489
490     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
491     {
492       int serverRank = itGlobalMap->first;
493       int indexSize = itGlobalMap->second.size();
494       const std::vector<size_t>& indexVec = itGlobalMap->second;
495       for (int idx = 0; idx < indexSize; ++idx)
496       {
497          itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
498          if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
499          {
500             if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
501               connectedDataSize_[serverRank] = 1;
502             else
503               ++connectedDataSize_[serverRank];
504          }
505       }
506     }
507
508     connectedServerRank_.clear();
509     for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
510       connectedServerRank_.push_back(itGlobalMap->first);
511     }
512
513     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
514   }
515
516   /*!
517      Compute the global of (client) grid to send to server with the global index of each element of grid
518      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
519      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
520      on each element whose size is much smaller than one of whole grid.
521      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
522      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
523   */
524   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
525                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
526   {
527     CContext* context = CContext::getCurrent();
528     CContextClient* client = context->client;
529     int serverSize = client->serverSize;
530     std::vector<CDomain*> domList = getDomains();
531     std::vector<CAxis*> axisList = getAxis();
532
533     // Some pre-calculations of global index on each element of current grid.
534     int nbElement = axis_domain_order.numElements();
535     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
536     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
537     std::vector<size_t> elementNGlobal(nbElement);
538     elementNGlobal[0] = 1;
539     size_t globalSize = 1;
540     for (int idx = 0; idx < nbElement; ++idx)
541     {
542       elementNGlobal[idx] = globalSize;
543       size_t elementSize;
544       size_t elementGlobalSize = 1;
545       if (2 == axis_domain_order(idx)) // This is domain
546       {
547         elementSize = domList[domainIdx]->i_index.numElements();
548         globalIndexElement[idx].resize(elementSize);
549         for (int jdx = 0; jdx < elementSize; ++jdx)
550         {
551           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
552         }
553         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
554         ++domainIdx;
555       }
556       else if (1 == axis_domain_order(idx))  // This is axis
557       {
558         elementSize = axisList[axisIdx]->index.numElements();
559         globalIndexElement[idx].resize(elementSize);
560         for (int jdx = 0; jdx < elementSize; ++jdx)
561         {
562           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
563         }
564         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
565         ++axisIdx;
566       }
567       else  // Of course, this is scalar
568       {
569         globalIndexElement[idx].resize(1);
570         globalIndexElement[idx](0) = 0;
571         elementGlobalSize = 1;
572       }
573       globalSize *= elementGlobalSize;
574     }
575
576     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
577     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
578     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
579     // Number of temporary distributed global index held by each client for each server
580     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
581     CArray<int,1> nbIndexOnServerTmp(serverSize);
582     for (int idx = 0; idx < nbElement; ++idx)
583     {
584       nbIndexOnServer = 0;
585       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
586       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
587       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
588       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
589       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
590       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
591                                                                    ite = globalIndexElementOnServerMap.end(), it;
592       for (it = itb; it != ite; ++it)
593       {
594         const std::vector<int>& tmp = it->second;
595         nbIndexOnServerTmp = 0;
596         for (int i = 0; i < tmp.size(); ++i)
597         {
598           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
599         }
600         nbIndexOnServer += nbIndexOnServerTmp;
601       }
602
603       for (int i = 0; i < serverSize; ++i)
604       {
605         if (0 != nbIndexOnServer(i))
606         {
607           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
608           elementOnServer[idx][i] = true;
609         }
610       }
611
612       nbIndexOnServer = 0;
613       for (it = itb; it != ite; ++it)
614       {
615         const std::vector<int>& tmp = it->second;
616         nbIndexOnServerTmp = 0;
617         for (int i = 0; i < tmp.size(); ++i)
618         {
619           if (0 == nbIndexOnServerTmp(tmp[i]))
620           {
621             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
622             ++nbIndexOnServerTmp(tmp[i]);
623           }
624         }
625         nbIndexOnServer += nbIndexOnServerTmp;
626       }
627     }
628
629    // Determine server which contain global source index
630    std::vector<bool> intersectedProc(serverSize, true);
631    for (int idx = 0; idx < nbElement; ++idx)
632    {
633      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
634                     intersectedProc.begin(), intersectedProc.begin(),
635                     std::logical_and<bool>());
636    }
637
638    std::vector<int> srcRank;
639    for (int idx = 0; idx < serverSize; ++idx)
640    {
641      if (intersectedProc[idx]) srcRank.push_back(idx);
642    }
643
644    // Compute the global index of grid from global index of each element.
645    for (int i = 0; i < srcRank.size(); ++i)
646    {
647      size_t ssize = 1;
648      int rankSrc = srcRank[i];
649      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
650      std::vector<size_t> currentIndex(nbElement,0);
651      for (int idx = 0; idx < nbElement; ++idx)
652      {
653        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
654        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
655      }
656      globalIndexOnServer[rankSrc].resize(ssize);
657
658      std::vector<int> idxLoop(nbElement,0);
659      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
660      size_t idx = 0;
661      while (idx < ssize)
662      {
663        for (int ind = 0; ind < nbElement; ++ind)
664        {
665          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
666          {
667            idxLoop[ind] = 0;
668            ++idxLoop[ind+1];
669          }
670
671          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
672        }
673
674        for (int ind = 0; ind < innnerLoopSize; ++ind)
675        {
676          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
677          size_t globalSrcIndex = 0;
678          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
679          {
680            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
681          }
682          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
683          ++idx;
684          ++idxLoop[0];
685        }
686      }
687    }
688   }
689   //----------------------------------------------------------------
690
691   CGrid* CGrid::createGrid(CDomain* domain)
692   {
693      std::vector<CDomain*> vecDom(1, domain);
694      std::vector<CAxis*> vecAxis;
695
696      return createGrid(vecDom, vecAxis);
697   }
698
699   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
700   {
701      std::vector<CDomain*> vecDom(1, domain);
702      std::vector<CAxis*> vecAxis(1, axis);
703
704      return createGrid(vecDom, vecAxis);
705   }
706
707   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
708                            const CArray<int,1>& axisDomainOrder)
709   {
710     std::vector<CScalar*> vecScalar;
711     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
712   }
713
714   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
715                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
716   {
717     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
718   }
719
720   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
721                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
722   {
723      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
724        ERROR("CGrid* CGrid::createGrid(...)",
725              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
726              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
727
728      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
729      grid->setDomainList(domains);
730      grid->setAxisList(axis);
731      grid->setScalarList(scalars);
732
733      // By default, domains are always the first elements of a grid
734      if (0 == axisDomainOrder.numElements())
735      {
736        int size = domains.size() + axis.size() + scalars.size();
737        int nb = 0;
738        grid->axis_domain_order.resize(size);
739        for (int i = 0; i < size; ++i)
740        {
741          if (i < domains.size()) {
742            grid->axis_domain_order(i) = 2;
743
744          }
745          else if ((scalars.size() < (size-nb)) < size) {
746            grid->axis_domain_order(i) = 1;
747          }
748          else
749            grid->axis_domain_order(i) = 0;
750          ++nb;
751        }
752      }
753      else
754      {
755        grid->axis_domain_order.resize(axisDomainOrder.numElements());
756        grid->axis_domain_order = axisDomainOrder;
757      }
758
759      grid->solveDomainAxisRefInheritance(true);
760
761      return grid;
762   }
763
764   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
765   {
766     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
767     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
768     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
769
770     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
771     {
772       CDomain* domain = CDomain::createDomain();
773       domain->duplicateAttributes(domainSrcTmp[idx]);
774       domain->duplicateTransformation(domainSrcTmp[idx]);
775       domain->solveRefInheritance(true);
776       domain->solveInheritanceTransformation();
777       domainSrc.push_back(domain);
778     }
779
780     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
781     {
782       CAxis* axis = CAxis::createAxis();
783       axis->duplicateAttributes(axisSrcTmp[idx]);
784       axis->duplicateTransformation(axisSrcTmp[idx]);
785       axis->solveRefInheritance(true);
786       axis->solveInheritanceTransformation();
787       axisSrc.push_back(axis);
788     }
789
790     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
791     {
792       CScalar* scalar = CScalar::createScalar();
793       scalar->duplicateAttributes(scalarSrcTmp[idx]);
794       scalar->duplicateTransformation(scalarSrcTmp[idx]);
795       scalar->solveRefInheritance(true);
796       scalar->solveInheritanceTransformation();
797       scalarSrc.push_back(scalar);
798     }
799
800      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
801
802      return grid;
803   }
804
805   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
806                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
807   {
808      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
809        ERROR("CGrid* CGrid::generateId(...)",
810              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
811              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
812
813      std::ostringstream id;
814
815      if (domains.empty() && axis.empty() && !scalars.empty())
816        id << "__scalar_";
817
818      if (0 != (domains.size() + axis.size() + scalars.size()))
819      {
820        id << "__grid";
821
822        if (0 == axisDomainOrder.numElements())
823        {
824          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
825          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
826          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
827        }
828        else
829        {
830          size_t iDomain = 0, iAxis = 0, iScalar = 0;
831          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
832          {
833            if (2 == axisDomainOrder(i))
834              id << "_" << domains[iDomain++]->getId();
835            else if (1 == axisDomainOrder(i))
836              id << "_" << axis[iAxis++]->getId();
837            else
838              id << "_" << scalars[iScalar++]->getId();
839          }
840        }
841
842        id << "__";
843      }
844
845      return id.str();
846   }
847
848   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
849   {
850     StdString idSrc  = gridSrc->getId();
851     StdString idDest = gridDest->getId();
852
853     std::ostringstream id;
854     id << idSrc << "__" << idDest;
855
856     return id.str();
857   }
858
859   //----------------------------------------------------------------
860
861   CDomainGroup* CGrid::getVirtualDomainGroup() const
862   {
863     return this->vDomainGroup_;
864   }
865
866   CAxisGroup* CGrid::getVirtualAxisGroup() const
867   {
868     return this->vAxisGroup_;
869   }
870
871   CScalarGroup* CGrid::getVirtualScalarGroup() const
872   {
873     return this->vScalarGroup_;
874   }
875
876   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
877   {
878     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
879     StdSize numElements = stored.numElements();
880     for (StdSize n = 0; n < numElements; ++n)
881     {
882       field[out_i(n)] = stored(n);
883     }
884   }
885
886   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
887   {
888     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
889     StdSize numElements = stored.numElements();
890     for (StdSize n = 0; n < numElements; ++n)
891     {
892       stored(n) = field[out_i(n)];
893     }
894   }
895
896   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
897   {
898     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
899     StdSize numElements = stored.numElements();
900     for (StdSize n = 0; n < numElements; ++n)
901     {
902       field[out_i(n)] = stored(n);
903     }
904   }
905
906   //----------------------------------------------------------------
907
908   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
909   {
910      const StdSize size = storeIndex_client.numElements();
911
912      stored.resize(size);
913      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
914   }
915
916   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
917   {
918      const StdSize size = storeIndex_client.numElements();
919
920      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
921   }
922
923  void CGrid::computeIndexScalarGrid()
924  {
925    CContext* context = CContext::getCurrent();
926    CContextClient* client=context->client;
927
928    storeIndex_client.resize(1);
929    storeIndex_client(0) = 0;
930    if (0 == client->clientRank)
931    {
932      for (int rank = 0; rank < client->serverSize; ++rank)
933        connectedDataSize_[rank] = 1;
934    }
935    isDataDistributed_ = false;
936  }
937
938  void CGrid::computeCompressedIndex()
939  {
940    compressedOutIndexFromClient = outIndexFromClient;
941
942    std::map<size_t, size_t> indexes;
943
944    {
945      std::map<int, CArray<size_t,1> >::const_iterator it = compressedOutIndexFromClient.begin();
946      std::map<int, CArray<size_t,1> >::const_iterator itEnd = compressedOutIndexFromClient.end();
947      for (; it != itEnd; ++it)
948      {
949        for (int i = 0; i < it->second.numElements(); ++i)
950          indexes.insert(std::make_pair(it->second(i), 0));
951      }
952    }
953
954    {
955      std::map<size_t, size_t>::iterator it = indexes.begin();
956      std::map<size_t, size_t>::iterator itEnd = indexes.end();
957      for (size_t i = 0; it != itEnd; ++it, ++i)
958        it->second = i;
959    }
960
961    {
962      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
963      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
964      for (; it != itEnd; ++it)
965      {
966        for (int i = 0; i < it->second.numElements(); ++i)
967          it->second(i) = indexes[it->second(i)];
968      }
969    }
970  }
971
972  void CGrid::sendIndexScalarGrid()
973  {
974    CContext* context = CContext::getCurrent();
975    CContextClient* client = context->client;
976
977    CEventClient event(getType(), EVENT_ID_INDEX);
978    list<CMessage> listMsg;
979    list<CArray<size_t,1> > listOutIndex;
980
981    if (0 == client->clientRank)
982    {
983      for (int rank = 0; rank < client->serverSize; ++rank)
984      {
985        int nb = 1;
986        storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(nb)));
987        listOutIndex.push_back(CArray<size_t,1>(nb));
988
989        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
990        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
991
992        for (int k = 0; k < nb; ++k)
993        {
994          outGlobalIndexOnServer(k) = 0;
995          outLocalIndexToServer(k)  = 0;
996        }
997
998        listMsg.push_back(CMessage());
999        listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
1000
1001        event.push(rank, 1, listMsg.back());
1002      }
1003
1004      client->sendEvent(event);
1005    }
1006    else
1007      client->sendEvent(event);
1008  }
1009
1010  void CGrid::sendIndex(void)
1011  {
1012    CContext* context = CContext::getCurrent();
1013    CContextClient* client = context->client;
1014
1015    CEventClient event(getType(), EVENT_ID_INDEX);
1016    int rank;
1017    list<CMessage> listMsg;
1018    list<CArray<size_t,1> > listOutIndex;
1019    const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
1020    CDistributionClient::GlobalLocalDataMap::const_iterator itIndex = globalLocalIndexSendToServer.begin(),
1021                                                           iteIndex = globalLocalIndexSendToServer.end();
1022
1023    if (!doGridHaveDataDistributed())
1024    {
1025      if (0 == client->clientRank)
1026      {
1027        int indexSize = globalLocalIndexSendToServer.size();
1028        CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1029        CArray<int,1> outLocalIndexToServer(indexSize);
1030        for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1031        {
1032          outGlobalIndexOnServer(idx) = itIndex->first;
1033          outLocalIndexToServer(idx) = itIndex->second;
1034        }
1035
1036        for (rank = 0; rank < client->serverSize; ++rank)
1037        {
1038          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1039          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1040
1041          listMsg.push_back(CMessage());
1042          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1043
1044          event.push(rank, 1, listMsg.back());
1045        }
1046
1047        client->sendEvent(event);
1048      }
1049      else
1050        client->sendEvent(event);
1051    }
1052    else
1053    {
1054      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
1055      itGlobalMap = globalIndexOnServer_.begin();
1056      iteGlobalMap = globalIndexOnServer_.end();
1057
1058      std::map<int,std::vector<int> >localIndexTmp;
1059      std::map<int,std::vector<size_t> > globalIndexTmp;
1060      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1061      {
1062        int serverRank = itGlobalMap->first;
1063        int indexSize = itGlobalMap->second.size();
1064        const std::vector<size_t>& indexVec = itGlobalMap->second;
1065        for (int idx = 0; idx < indexSize; ++idx)
1066        {
1067          itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
1068          if (iteIndex != itIndex)
1069          {
1070            globalIndexTmp[serverRank].push_back(itIndex->first);
1071            localIndexTmp[serverRank].push_back(itIndex->second);
1072          }
1073        }
1074      }
1075
1076      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
1077      {
1078        rank = connectedServerRank_[ns];
1079        int nb = 0;
1080        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
1081          nb = globalIndexTmp[rank].size();
1082
1083        storeIndex_toSrv.insert(make_pair(rank, CArray<int,1>(nb)));
1084        listOutIndex.push_back(CArray<size_t,1>(nb));
1085
1086        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
1087        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1088
1089        for (int k = 0; k < nb; ++k)
1090        {
1091          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1092          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1093        }
1094
1095        listMsg.push_back(CMessage());
1096        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1097
1098        event.push(rank, nbSenders[rank], listMsg.back());
1099      }
1100
1101      client->sendEvent(event);
1102    }
1103  }
1104
1105  void CGrid::recvIndex(CEventServer& event)
1106  {
1107    string gridId;
1108    vector<int> ranks;
1109    vector<CBufferIn*> buffers;
1110
1111    list<CEventServer::SSubEvent>::iterator it;
1112    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1113    {
1114      ranks.push_back(it->rank);
1115      CBufferIn* buffer = it->buffer;
1116      *buffer >> gridId;
1117      buffers.push_back(buffer);
1118    }
1119    get(gridId)->recvIndex(ranks, buffers);
1120  }
1121
1122  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
1123                                         const std::vector<CAxis*>& axis,
1124                                         const std::vector<CScalar*>& scalars,
1125                                         const CArray<int,1>& axisDomainOrder)
1126  {
1127    globalDim_.resize(domains.size()*2+axis.size()+scalars.size());
1128    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1129    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1130    {
1131      if (2 == axisDomainOrder(i))
1132      {
1133        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1134        {
1135          positionDimensionDistributed_ = idx;
1136        }
1137        else
1138        {
1139          positionDimensionDistributed_ = idx +1;
1140        }
1141
1142        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
1143        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
1144
1145        ++idxDomain;
1146        idx += 2;
1147      }
1148      else if (1 == axisDomainOrder(i))
1149      {
1150        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
1151        ++idxAxis;
1152        ++idx;
1153      }
1154      else
1155      {
1156        globalDim_[idx] = 1;
1157        ++idxScalar;
1158        ++idx;
1159      }
1160    }
1161  }
1162
1163  std::vector<int> CGrid::getGlobalDimension()
1164  {
1165    return globalDim_;
1166  }
1167
1168  bool CGrid::isScalarGrid() const
1169  {
1170    return (axisList_.empty() && domList_.empty());
1171  }
1172
1173  /*!
1174    Verify whether one server need to write data
1175    There are some cases on which one server has nodata to write. For example, when we
1176    just only want to zoom on a domain.
1177  */
1178  bool CGrid::doGridHaveDataToWrite()
1179  {
1180     return (0 != writtenDataSize_);
1181  }
1182
1183  /*!
1184    Return size of data which is written on each server
1185    Whatever dimension of a grid, data which are written on server must be presented as
1186    an one dimension array.
1187    \return size of data written on server
1188  */
1189  size_t CGrid::getWrittenDataSize() const
1190  {
1191    return writtenDataSize_;
1192  }
1193
1194  /*!
1195    Returns the number of indexes written by each server.
1196    \return the number of indexes written by each server
1197  */
1198  int CGrid::getNumberWrittenIndexes() const
1199  {
1200    return numberWrittenIndexes_;
1201  }
1202
1203  /*!
1204    Returns the total number of indexes written by the servers.
1205    \return the total number of indexes written by the servers
1206  */
1207  int CGrid::getTotalNumberWrittenIndexes() const
1208  {
1209    return totalNumberWrittenIndexes_;
1210  }
1211
1212  /*!
1213    Returns the offset of indexes written by each server.
1214    \return the offset of indexes written by each server
1215  */
1216  int CGrid::getOffsetWrittenIndexes() const
1217  {
1218    return offsetWrittenIndexes_;
1219  }
1220
1221  CDistributionServer* CGrid::getDistributionServer()
1222  {
1223    return serverDistribution_;
1224  }
1225
1226  CDistributionClient* CGrid::getDistributionClient()
1227  {
1228    return clientDistribution_;
1229  }
1230
1231  bool CGrid::doGridHaveDataDistributed()
1232  {
1233    if (isScalarGrid()) return false;
1234    else
1235      return isDataDistributed_;
1236  }
1237
1238  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1239  {
1240    CContext* context = CContext::getCurrent();
1241    CContextServer* server = context->server;
1242    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
1243    connectedServerRank_ = ranks;
1244
1245    for (int n = 0; n < ranks.size(); n++)
1246    {
1247      int rank = ranks[n];
1248      CBufferIn& buffer = *buffers[n];
1249
1250      buffer >> isDataDistributed_ >> isCompressible_;
1251      size_t dataSize = 0;
1252
1253      if (isScalarGrid())
1254      {
1255        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
1256        CArray<size_t,1> outIndex;
1257        buffer >> outIndex;
1258        outIndexFromClient.insert(std::make_pair(rank, outIndex));
1259        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
1260        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1261                                                      nZoomBeginGlobal, nGlob);
1262        return;
1263      }
1264
1265      if (0 == serverDistribution_)
1266      {
1267        int idx = 0, numElement = axis_domain_order.numElements();
1268        int ssize = numElement;
1269        std::vector<int> indexMap(numElement);
1270        for (int i = 0; i < numElement; ++i)
1271        {
1272          indexMap[i] = idx;
1273          if (2 == axis_domain_order(i))
1274          {
1275            ++ssize;
1276            idx += 2;
1277          }
1278          else
1279            ++idx;
1280        }
1281
1282        int axisId = 0, domainId = 0, scalarId = 0;
1283        std::vector<CDomain*> domainList = getDomains();
1284        std::vector<CAxis*> axisList = getAxis();
1285        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
1286        for (int i = 0; i < numElement; ++i)
1287        {
1288          if (2 == axis_domain_order(i)) //domain
1289          {
1290            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
1291            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
1292            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
1293            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1294
1295            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
1296            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
1297            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
1298            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1299            ++domainId;
1300          }
1301          else if (1 == axis_domain_order(i)) // axis
1302          {
1303            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1304            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1305            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
1306            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1307            ++axisId;
1308          }
1309          else // scalar
1310          {
1311            nZoomBegin[indexMap[i]] = 0;
1312            nZoomSize[indexMap[i]]  = 1;
1313            nZoomBeginGlobal[indexMap[i]] = 0;
1314            nGlob[indexMap[i]] = 1;
1315            ++scalarId;
1316          }
1317        }
1318        dataSize = 1;
1319        for (int i = 0; i < nZoomSize.size(); ++i)
1320          dataSize *= nZoomSize[i];
1321
1322        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1323                                                      nZoomBeginGlobal, nGlob);
1324      }
1325
1326      CArray<size_t,1> outIndex;
1327      buffer >> outIndex;
1328      if (isDataDistributed_)
1329        serverDistribution_->computeLocalIndex(outIndex);
1330      else
1331      {
1332        dataSize = outIndex.numElements();
1333        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
1334      }
1335      writtenDataSize_ += dataSize;
1336
1337      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1338      connectedDataSize_[rank] = outIndex.numElements();
1339      numberWrittenIndexes_ += outIndex.numElements();
1340    }
1341
1342    if (isDataDistributed_)
1343    {
1344      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1345      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1346      offsetWrittenIndexes_ -= numberWrittenIndexes_;
1347    }
1348    else
1349      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1350
1351    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1352  }
1353
1354   /*!
1355   \brief Dispatch event received from client
1356      Whenever a message is received in buffer of server, it will be processed depending on
1357   its event type. A new event type should be added in the switch list to make sure
1358   it processed on server side.
1359   \param [in] event: Received message
1360   */
1361  bool CGrid::dispatchEvent(CEventServer& event)
1362  {
1363
1364    if (SuperClass::dispatchEvent(event)) return true;
1365    else
1366    {
1367      switch(event.type)
1368      {
1369        case EVENT_ID_INDEX :
1370          recvIndex(event);
1371          return true;
1372          break;
1373
1374         case EVENT_ID_ADD_DOMAIN :
1375           recvAddDomain(event);
1376           return true;
1377           break;
1378
1379         case EVENT_ID_ADD_AXIS :
1380           recvAddAxis(event);
1381           return true;
1382           break;
1383
1384         case EVENT_ID_ADD_SCALAR :
1385           recvAddScalar(event);
1386           return true;
1387           break;
1388        default :
1389          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1390                << "Unknown Event");
1391          return false;
1392      }
1393    }
1394  }
1395
1396   ///---------------------------------------------------------------
1397
1398   CDomain* CGrid::addDomain(const std::string& id)
1399   {
1400     order_.push_back(2);
1401     axis_domain_order.resize(order_.size());
1402     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1403     return vDomainGroup_->createChild(id);
1404   }
1405
1406   CAxis* CGrid::addAxis(const std::string& id)
1407   {
1408     order_.push_back(1);
1409     axis_domain_order.resize(order_.size());
1410     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1411     return vAxisGroup_->createChild(id);
1412   }
1413
1414   CScalar* CGrid::addScalar(const std::string& id)
1415   {
1416     order_.push_back(0);
1417     axis_domain_order.resize(order_.size());
1418     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1419     return vScalarGroup_->createChild(id);
1420   }
1421
1422   //! Change virtual field group to a new one
1423   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1424   {
1425      this->vDomainGroup_ = newVDomainGroup;
1426   }
1427
1428   //! Change virtual variable group to new one
1429   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1430   {
1431      this->vAxisGroup_ = newVAxisGroup;
1432   }
1433
1434   //! Change virtual variable group to new one
1435   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1436   {
1437      this->vScalarGroup_ = newVScalarGroup;
1438   }
1439
1440   //----------------------------------------------------------------
1441   //! Create virtual field group, which is done normally on initializing file
1442   void CGrid::setVirtualDomainGroup(void)
1443   {
1444      this->setVirtualDomainGroup(CDomainGroup::create());
1445   }
1446
1447   //! Create virtual variable group, which is done normally on initializing file
1448   void CGrid::setVirtualAxisGroup(void)
1449   {
1450      this->setVirtualAxisGroup(CAxisGroup::create());
1451   }
1452
1453   //! Create virtual variable group, which is done normally on initializing file
1454   void CGrid::setVirtualScalarGroup(void)
1455   {
1456      this->setVirtualScalarGroup(CScalarGroup::create());
1457   }
1458
1459   /*!
1460   \brief Send a message to create a domain on server side
1461   \param[in] id String identity of domain that will be created on server
1462   */
1463   void CGrid::sendAddDomain(const string& id)
1464   {
1465    CContext* context=CContext::getCurrent();
1466
1467    if (! context->hasServer )
1468    {
1469       CContextClient* client=context->client;
1470
1471       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1472       if (client->isServerLeader())
1473       {
1474         CMessage msg;
1475         msg<<this->getId();
1476         msg<<id;
1477         const std::list<int>& ranks = client->getRanksServerLeader();
1478         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1479           event.push(*itRank,1,msg);
1480         client->sendEvent(event);
1481       }
1482       else client->sendEvent(event);
1483    }
1484   }
1485
1486   /*!
1487   \brief Send a message to create an axis on server side
1488   \param[in] id String identity of axis that will be created on server
1489   */
1490   void CGrid::sendAddAxis(const string& id)
1491   {
1492    CContext* context=CContext::getCurrent();
1493
1494    if (! context->hasServer )
1495    {
1496       CContextClient* client=context->client;
1497
1498       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1499       if (client->isServerLeader())
1500       {
1501         CMessage msg;
1502         msg<<this->getId();
1503         msg<<id;
1504         const std::list<int>& ranks = client->getRanksServerLeader();
1505         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1506           event.push(*itRank,1,msg);
1507         client->sendEvent(event);
1508       }
1509       else client->sendEvent(event);
1510    }
1511   }
1512
1513   /*!
1514   \brief Send a message to create a scalar on server side
1515   \param[in] id String identity of scalar that will be created on server
1516   */
1517   void CGrid::sendAddScalar(const string& id)
1518   {
1519    CContext* context=CContext::getCurrent();
1520
1521    if (! context->hasServer )
1522    {
1523       CContextClient* client=context->client;
1524
1525       CEventClient event(this->getType(),EVENT_ID_ADD_SCALAR);
1526       if (client->isServerLeader())
1527       {
1528         CMessage msg;
1529         msg<<this->getId();
1530         msg<<id;
1531         const std::list<int>& ranks = client->getRanksServerLeader();
1532         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1533           event.push(*itRank,1,msg);
1534         client->sendEvent(event);
1535       }
1536       else client->sendEvent(event);
1537    }
1538   }
1539
1540   /*!
1541   \brief Receive a message annoucing the creation of a domain on server side
1542   \param[in] event Received event
1543   */
1544   void CGrid::recvAddDomain(CEventServer& event)
1545   {
1546
1547      CBufferIn* buffer = event.subEvents.begin()->buffer;
1548      string id;
1549      *buffer >> id;
1550      get(id)->recvAddDomain(*buffer);
1551   }
1552
1553   /*!
1554   \brief Receive a message annoucing the creation of a domain on server side
1555   \param[in] buffer Buffer containing message
1556   */
1557   void CGrid::recvAddDomain(CBufferIn& buffer)
1558   {
1559      string id;
1560      buffer >> id;
1561      addDomain(id);
1562   }
1563
1564   /*!
1565   \brief Receive a message annoucing the creation of an axis on server side
1566   \param[in] event Received event
1567   */
1568   void CGrid::recvAddAxis(CEventServer& event)
1569   {
1570
1571      CBufferIn* buffer = event.subEvents.begin()->buffer;
1572      string id;
1573      *buffer >> id;
1574      get(id)->recvAddAxis(*buffer);
1575   }
1576
1577   /*!
1578   \brief Receive a message annoucing the creation of an axis on server side
1579   \param[in] buffer Buffer containing message
1580   */
1581   void CGrid::recvAddAxis(CBufferIn& buffer)
1582   {
1583      string id;
1584      buffer >> id;
1585      addAxis(id);
1586   }
1587
1588   /*!
1589   \brief Receive a message annoucing the creation of an scalar on server side
1590   \param[in] event Received event
1591   */
1592   void CGrid::recvAddScalar(CEventServer& event)
1593   {
1594
1595      CBufferIn* buffer = event.subEvents.begin()->buffer;
1596      string id;
1597      *buffer >> id;
1598      get(id)->recvAddScalar(*buffer);
1599   }
1600
1601   /*!
1602   \brief Receive a message annoucing the creation of an scalar on server side
1603   \param[in] buffer Buffer containing message
1604   */
1605   void CGrid::recvAddScalar(CBufferIn& buffer)
1606   {
1607      string id;
1608      buffer >> id;
1609      addScalar(id);
1610   }
1611
1612  /*!
1613  \brief Solve domain and axis references
1614  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1615  all attributes from their parents, they should be processed with this function
1616  \param[in] apply inherit all attributes of parents (true)
1617  */
1618  void CGrid::solveDomainAxisRefInheritance(bool apply)
1619  {
1620    CContext* context = CContext::getCurrent();
1621    unsigned int vecSize, i;
1622    std::vector<StdString>::iterator it, itE;
1623    setDomainList();
1624    it = domList_.begin(); itE = domList_.end();
1625    for (; it != itE; ++it)
1626    {
1627      CDomain* pDom = CDomain::get(*it);
1628      if (context->hasClient)
1629      {
1630        pDom->solveRefInheritance(apply);
1631        pDom->solveInheritanceTransformation();
1632      }
1633    }
1634
1635    setAxisList();
1636    it = axisList_.begin(); itE = axisList_.end();
1637    for (; it != itE; ++it)
1638    {
1639      CAxis* pAxis = CAxis::get(*it);
1640      if (context->hasClient)
1641      {
1642        pAxis->solveRefInheritance(apply);
1643        pAxis->solveInheritanceTransformation();
1644      }
1645    }
1646
1647    setScalarList();
1648    it = scalarList_.begin(); itE = scalarList_.end();
1649    for (; it != itE; ++it)
1650    {
1651      CScalar* pScalar = CScalar::get(*it);
1652      if (context->hasClient)
1653      {
1654        pScalar->solveRefInheritance(apply);
1655        pScalar->solveInheritanceTransformation();
1656      }
1657    }
1658  }
1659
1660  bool CGrid::isTransformed()
1661  {
1662    return isTransformed_;
1663  }
1664
1665  void CGrid::setTransformed()
1666  {
1667    isTransformed_ = true;
1668  }
1669
1670  CGridTransformation* CGrid::getTransformations()
1671  {
1672    return transformations_;
1673  }
1674
1675  void CGrid::addTransGridSource(CGrid* gridSrc)
1676  {
1677    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1678      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1679  }
1680
1681  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1682  {
1683    return gridSrc_;
1684  }
1685
1686  /*!
1687     Complete all the necessary (and lacking) attributes of a grid
1688     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1689  */
1690  void CGrid::completeGrid(CGrid* transformGridSrc)
1691  {
1692    if (0 != transformGridSrc)
1693    {
1694      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1695      {
1696        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1697             << "Two grids have different dimension size"
1698             << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1699             << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1700      }
1701    }
1702
1703    if (isGenerated()) return;
1704    setGenerated();
1705
1706    CGridGenerate gridGenerate(this, transformGridSrc);
1707    gridGenerate.completeGrid();
1708  }
1709
1710  bool CGrid::isGenerated()
1711  {
1712    return isGenerated_;
1713  }
1714
1715  void CGrid::setGenerated()
1716  {
1717    isGenerated_ = true;
1718  }
1719
1720  void CGrid::transformGrid(CGrid* transformGridSrc)
1721  {
1722    if (!transformGridSrc)
1723      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1724            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1725
1726    if (isTransformed()) return;
1727    setTransformed();
1728    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1729    {
1730      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1731           << "Two grids have different dimension size"
1732           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1733           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1734    }
1735    else
1736    {
1737    }
1738
1739    transformations_ = new CGridTransformation(this, transformGridSrc);
1740    transformations_->computeAll();
1741    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1742
1743    // Ok, now need to compute index of grid source
1744    transformGridSrc->checkMaskIndex(false);
1745  }
1746
1747  bool CGrid::hasTransform()
1748  {
1749    if (hasTransform_) return hasTransform_;
1750
1751    std::vector<CDomain*> domList = getDomains();
1752    std::vector<CAxis*> axisList = getAxis();
1753    std::vector<CScalar*> scalarList = getScalars();
1754
1755    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
1756    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
1757    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
1758
1759    return hasTransform_;
1760  }
1761
1762  /*!
1763  \brief Get the list of domain pointers
1764  \return list of domain pointers
1765  */
1766  std::vector<CDomain*> CGrid::getDomains()
1767  {
1768    std::vector<CDomain*> domList;
1769    if (!domList_.empty())
1770    {
1771      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1772    }
1773    return domList;
1774  }
1775
1776  /*!
1777  \brief Get the list of  axis pointers
1778  \return list of axis pointers
1779  */
1780  std::vector<CAxis*> CGrid::getAxis()
1781  {
1782    std::vector<CAxis*> aList;
1783    if (!axisList_.empty())
1784      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1785
1786    return aList;
1787  }
1788
1789  /*!
1790  \brief Get the list of  axis pointers
1791  \return list of axis pointers
1792  */
1793  std::vector<CScalar*> CGrid::getScalars()
1794  {
1795    std::vector<CScalar*> sList;
1796    if (!scalarList_.empty())
1797      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
1798
1799    return sList;
1800  }
1801
1802  /*!
1803  \brief Set domain(s) of a grid from a list
1804  \param[in] domains list of domains
1805  */
1806  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1807  {
1808    if (isDomListSet) return;
1809    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1810    if (!domains.empty() && domList.empty())
1811    {
1812      for (int i = 0; i < domains.size(); ++i)
1813        this->getVirtualDomainGroup()->addChild(domains[i]);
1814      domList = this->getVirtualDomainGroup()->getAllChildren();
1815    }
1816
1817    if (!domList.empty())
1818    {
1819      int sizeDom = domList.size();
1820      domList_.resize(sizeDom);
1821      for (int i = 0; i < sizeDom; ++i)
1822      {
1823        domList_[i] = domList[i]->getId();
1824      }
1825      isDomListSet = true;
1826    }
1827
1828  }
1829
1830  /*!
1831  \brief Set axis(s) of a grid from a list
1832  \param[in] axis list of axis
1833  */
1834  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1835  {
1836    if (isAxisListSet) return;
1837    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1838    if (!axis.empty() && aList.empty())
1839    {
1840      for (int i = 0; i < axis.size(); ++i)
1841        this->getVirtualAxisGroup()->addChild(axis[i]);
1842      aList = this->getVirtualAxisGroup()->getAllChildren();
1843    }
1844
1845    if (!aList.empty())
1846    {
1847      int sizeAxis = aList.size();
1848      axisList_.resize(sizeAxis);
1849      for (int i = 0; i < sizeAxis; ++i)
1850      {
1851        axisList_[i] = aList[i]->getId();
1852      }
1853      isAxisListSet = true;
1854    }
1855  }
1856
1857  /*!
1858  \brief Set scalar(s) of a grid from a list
1859  \param[in] scalars list of scalars
1860  */
1861  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
1862  {
1863    if (isScalarListSet) return;
1864    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
1865    if (!scalars.empty() && sList.empty())
1866    {
1867      for (int i = 0; i < scalars.size(); ++i)
1868        this->getVirtualScalarGroup()->addChild(scalars[i]);
1869      sList = this->getVirtualScalarGroup()->getAllChildren();
1870    }
1871
1872    if (!sList.empty())
1873    {
1874      int sizeScalar = sList.size();
1875      scalarList_.resize(sizeScalar);
1876      for (int i = 0; i < sizeScalar; ++i)
1877      {
1878        scalarList_[i] = sList[i]->getId();
1879      }
1880      isScalarListSet = true;
1881    }
1882  }
1883
1884  /*!
1885  \brief Get list of id of domains
1886  \return id list of domains
1887  */
1888  std::vector<StdString> CGrid::getDomainList()
1889  {
1890    setDomainList();
1891    return domList_;
1892  }
1893
1894  /*!
1895  \brief Get list of id of axis
1896  \return id list of axis
1897  */
1898  std::vector<StdString> CGrid::getAxisList()
1899  {
1900    setAxisList();
1901    return axisList_;
1902  }
1903
1904  /*!
1905  \brief Get list of id of scalar
1906  \return id list of scalar
1907  */
1908  std::vector<StdString> CGrid::getScalarList()
1909  {
1910    setScalarList();
1911    return scalarList_;
1912  }
1913
1914  /*!
1915    Send all attributes of domains from client to server
1916  */
1917  void CGrid::sendAllDomains()
1918  {
1919    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1920    int dSize = domList.size();
1921    for (int i = 0; i < dSize; ++i)
1922    {
1923      sendAddDomain(domList[i]->getId());
1924      domList[i]->sendAllAttributesToServer();
1925    }
1926  }
1927
1928  /*!
1929    Send all attributes of axis from client to server
1930  */
1931  void CGrid::sendAllAxis()
1932  {
1933    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1934    int aSize = aList.size();
1935
1936    for (int i = 0; i < aSize; ++i)
1937    {
1938      sendAddAxis(aList[i]->getId());
1939      aList[i]->sendAllAttributesToServer();
1940    }
1941  }
1942
1943  /*!
1944    Send all attributes of scalars from client to server
1945  */
1946  void CGrid::sendAllScalars()
1947  {
1948    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
1949    int sSize = sList.size();
1950
1951    for (int i = 0; i < sSize; ++i)
1952    {
1953      sendAddScalar(sList[i]->getId());
1954      sList[i]->sendAllAttributesToServer();
1955    }
1956  }
1957
1958  /*!
1959    Parse a grid, for now, it contains only domain, axis and scalar
1960  */
1961  void CGrid::parse(xml::CXMLNode& node)
1962  {
1963    SuperClass::parse(node);
1964
1965    if (node.goToChildElement())
1966    {
1967      StdString domainName("domain");
1968      StdString axisName("axis");
1969      StdString scalarName("scalar");
1970      do
1971      {
1972        if (node.getElementName() == domainName) {
1973          order_.push_back(2);
1974          this->getVirtualDomainGroup()->parseChild(node);
1975        }
1976        if (node.getElementName() == axisName) {
1977          order_.push_back(1);
1978          this->getVirtualAxisGroup()->parseChild(node);
1979        }
1980        if (node.getElementName() == scalarName) {
1981          order_.push_back(0);
1982          this->getVirtualScalarGroup()->parseChild(node);
1983        }
1984      } while (node.goToNextElement());
1985      node.goToParentElement();
1986    }
1987
1988    if (!order_.empty())
1989    {
1990      int sizeOrd = order_.size();
1991      axis_domain_order.resize(sizeOrd);
1992      for (int i = 0; i < sizeOrd; ++i)
1993      {
1994        axis_domain_order(i) = order_[i];
1995      }
1996    }
1997
1998    setDomainList();
1999    setAxisList();
2000    setScalarList();
2001   }
2002} // namespace xios
Note: See TracBrowser for help on using the repository browser.