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

Last change on this file since 957 was 957, checked in by rlacroix, 6 years ago

Fix a possible crash caused by an infinite recursion.

The way virtual groups were handled could cause id clashes which lead to have groups containing themselves.

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