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

Last change on this file since 967 was 967, checked in by mhnguyen, 6 years ago

Ticket 106: Reading a scalar from file

+) Add method to read scalar value
+) Modify the way to send/receive scalar (and non-distributed) data

Test
+) On Curie
+) OK

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