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

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

Correcting a bug on reading non-distributed data in server mode.

+) Non distributed data read by all servers then transfered back to ALL clients

Test
+) On Curie
+) Work

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