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

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

Correcting minor bug which can cause reading problem.

+) Make sure grid created by generate_domain_rectilinear be sent to server

Test
+) On Curie
+) OK

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