source: XIOS/dev/dev_olga/src/node/grid.cpp @ 987

Last change on this file since 987 was 987, checked in by mhnguyen, 7 years ago

First working version.
There are more things to do with it

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