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

Last change on this file since 1003 was 1003, checked in by mhnguyen, 8 years ago

Correcting the behavior of arithmetic expression in a field which has no reference to another field (no field_ref).
The order of filter chaining is mentioned in r998

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