source: XIOS/dev/branch_yushan_merged/src/node/grid.cpp @ 1134

Last change on this file since 1134 was 1134, checked in by yushan, 4 years ago

branch merged with trunk r1130

  • 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.9 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20
21namespace xios {
22
23   /// ////////////////////// Dfinitions ////////////////////// ///
24
25   CGrid::CGrid(void)
26      : CObjectTemplate<CGrid>(), CGridAttributes()
27      , isChecked(false), isDomainAxisChecked(false)
28      , vDomainGroup_(), domList_(), isDomListSet(false)
29      , vAxisGroup_(), axisList_(), isAxisListSet(false)
30      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
31      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
32      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
33      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
34      , transformations_(0), isTransformed_(false)
35      , axisPositionInGrid_(), 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      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
52      , transformations_(0), isTransformed_(false)
53      , axisPositionInGrid_(), 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)
77   {
78      return getGlobalDimension().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(getGlobalDimension(),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     this->isDomainAxisChecked = areAttributesChecked;
236   }
237
238   void CGrid::solveDomainAxisBaseRef()
239   {
240     if (this->hasDomainAxisBaseRef_) return;
241     // Account for the scalar attributes
242     std::vector<CScalar*> scalarList = getScalars();
243     for (size_t i = 0; i < scalarList.size(); ++i)
244     {
245       scalarList[i]->setAttributesReference();
246     }
247
248     // Account for the axis attributes
249     std::vector<CAxis*> axisList = getAxis();
250     for (size_t i = 0; i < axisList.size(); ++i)
251     {
252       axisList[i]->setAttributesReference();
253     }
254
255     // Account for the domain attributes
256     std::vector<CDomain*> domList = getDomains();
257     for (size_t i = 0; i < domList.size(); ++i)
258     {
259       domList[i]->setAttributesReference();
260     }
261
262     this->hasDomainAxisBaseRef_ = true;
263   }
264
265   void CGrid::checkEligibilityForCompressedOutput()
266   {
267     // We don't check if the mask is valid here, just if a mask has been defined at this point.
268     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
269   }
270
271   void CGrid::checkMaskIndex(bool doSendingIndex)
272   {
273     CContext* context = CContext::getCurrent();
274     CContextClient* client=context->client;
275
276     if (isScalarGrid())
277     {
278       if (context->hasClient)
279          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
280
281       if (this->isChecked) return;
282
283       if (context->hasClient)
284       {
285          this->computeIndexScalarGrid();
286       }
287
288       if (!(this->hasTransform() && !this->isTransformed()))
289        this->isChecked = true;
290       return;
291     }
292
293     if (context->hasClient)
294      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
295
296     if (this->isChecked) return;
297
298     if (context->hasClient)
299     {
300        this->checkAttributesAfterTransformation();
301        this->checkMask();
302        this->computeIndex();
303     }
304
305     if (!(this->hasTransform() && !this->isTransformed())) 
306      this->isChecked = true;
307
308     if (!(this->hasTransform() && (!this->isGenerated())))
309      this->isChecked = true; 
310   }
311
312   void CGrid::createMask(void)
313   {
314      using namespace std;
315      std::vector<CDomain*> domainP = this->getDomains();
316      std::vector<CAxis*> axisP = this->getAxis();
317      int dim = domainP.size() * 2 + axisP.size();
318
319      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
320      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
321      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
322      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
323
324      switch (dim) {
325        case 1:
326          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
327          break;
328        case 2:
329          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
330          break;
331        case 3:
332          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
333          break;
334        case 4:
335          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true);
336          break;
337        case 5:
338          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true);
339          break;
340        case 6:
341          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true);
342          break;
343        case 7:
344          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true);
345          break;
346        default:
347          break;
348      }
349   }
350
351   void CGrid::checkMask(void)
352   {
353      using namespace std;
354      std::vector<CDomain*> domainP = this->getDomains();
355      std::vector<CAxis*> axisP = this->getAxis();
356      int dim = domainP.size() * 2 + axisP.size();
357
358      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
359      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
360      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
361      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
362
363      switch (dim) {
364        case 1:
365          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
366          break;
367        case 2:
368          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
369          break;
370        case 3:
371          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
372          break;
373        case 4:
374          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order);
375          break;
376        case 5:
377          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order);
378          break;
379        case 6:
380          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order);
381          break;
382        case 7:
383          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order);
384          break;
385        default:
386          break;
387      }
388   }
389
390   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
391   {
392      using namespace std;
393      std::vector<CDomain*> domainP = this->getDomains();
394      std::vector<CAxis*> axisP = this->getAxis();
395      int dim = domainP.size() * 2 + axisP.size();
396
397      switch (dim) {
398        case 1:
399          modifyGridMask(mask_1d, indexToModify);
400          break;
401        case 2:
402          modifyGridMask(mask_2d, indexToModify);
403          break;
404        case 3:
405          modifyGridMask(mask_3d, indexToModify);
406          break;
407        case 4:
408          modifyGridMask(mask_1d, indexToModify);
409          break;
410        case 5:
411          modifyGridMask(mask_2d, indexToModify);
412          break;
413        case 6:
414          modifyGridMask(mask_3d, indexToModify);
415          break;
416        case 7:
417          modifyGridMask(mask_3d, indexToModify);
418          break;
419        default:
420          break;
421      }
422   }
423
424   //---------------------------------------------------------------
425
426   void CGrid::solveDomainRef(bool sendAtt)
427   {
428      setDomainList();
429      std::vector<CDomain*> domListP = this->getDomains();
430      if (!domListP.empty())
431      {
432        for (int i = 0; i < domListP.size(); ++i)
433        {
434          if (sendAtt) domListP[i]->sendCheckedAttributes();
435          else domListP[i]->checkAttributesOnClient();
436        }
437      }
438   }
439
440   //---------------------------------------------------------------
441
442   void CGrid::solveAxisRef(bool sendAtt)
443   {
444      setAxisList();
445      std::vector<CAxis*> axisListP = this->getAxis();
446      if (!axisListP.empty())
447      {
448        int idx = 0;
449        axisPositionInGrid_.resize(0);
450        for (int i = 0; i < axis_domain_order.numElements(); ++i)
451        {
452          int elementDimension = axis_domain_order(i);
453          if (1 == elementDimension)
454          {
455            axisPositionInGrid_.push_back(idx);
456            ++idx;
457          }
458          else if (2 == elementDimension) idx += 2;
459        }
460
461        for (int i = 0; i < axisListP.size(); ++i)
462        {
463          if (sendAtt)
464            axisListP[i]->sendCheckedAttributes(getGlobalDimension(),axisPositionInGrid_[i]);
465          else
466            axisListP[i]->checkAttributesOnClient();
467        }
468      }
469   }
470
471   //---------------------------------------------------------------
472
473   void CGrid::solveScalarRef(bool sendAtt)
474   {
475      setScalarList();
476      std::vector<CScalar*> scalarListP = this->getScalars();
477      if (!scalarListP.empty())
478      {
479        for (int i = 0; i < scalarListP.size(); ++i)
480        {
481          /*Nothing to do for now */
482//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
483//          else scalarListP[i]->checkAttributesOnClient();
484        }
485      }
486   }
487
488   std::vector<int> CGrid::getAxisPositionInGrid() const
489   {
490     return axisPositionInGrid_;
491   }
492
493   //---------------------------------------------------------------
494
495   /*!
496     Compute the global index of grid to send to server as well as the connected server of the current client.
497     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
498     their global index. We can have a map of global index of grid and local index that each client holds
499     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
500     of the current client.
501   */
502   void CGrid::computeIndex(void)
503   {
504     CContext* context = CContext::getCurrent();
505     CContextClient* client = context->client;
506
507     // First of all, compute distribution on client side
508     clientDistribution_ = new CDistributionClient(client->clientRank, this);
509     // Get local data index on client
510     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
511     int nbStoreIndex = storeIndex_client.numElements();
512     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
513     isDataDistributed_= clientDistribution_->isDataDistributed();
514
515     connectedServerRank_.clear();
516
517     if (!doGridHaveDataDistributed())
518     {
519        if (client->isServerLeader())
520        {
521          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
522          const std::list<int>& ranks = client->getRanksServerLeader();
523          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
524          {
525            connectedServerRank_.push_back(*itRank);
526            connectedDataSize_[*itRank] = ssize;
527          }
528        }
529        return;
530     }
531
532     // Compute mapping between client and server
533     std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
534     CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
535     serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
536                                                                client->clientRank,
537                                                                client->clientSize,
538                                                                axis_domain_order,
539                                                                getDistributedDimension());
540     computeIndexByElement(indexServerOnElement, globalIndexOnServer_);
541
542     const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
543     CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
544     CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
545     itGlobalMap  = itbGlobalMap = globalIndexOnServer_.begin();
546     iteGlobalMap = globalIndexOnServer_.end();
547
548     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
549     {
550       int serverRank = itGlobalMap->first;
551       int indexSize = itGlobalMap->second.size();
552       const std::vector<size_t>& indexVec = itGlobalMap->second;
553       for (int idx = 0; idx < indexSize; ++idx)
554       {
555          itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
556          if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
557          {
558             if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
559               connectedDataSize_[serverRank] = 1;
560             else
561               ++connectedDataSize_[serverRank];
562          }
563       }
564     }
565
566     for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
567       connectedServerRank_.push_back(itGlobalMap->first);
568     }
569
570     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
571   }
572
573   /*!
574      Compute the global of (client) grid to send to server with the global index of each element of grid
575      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
576      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
577      on each element whose size is much smaller than one of whole grid.
578      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
579      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
580   */
581   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
582                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
583   {
584     CContext* context = CContext::getCurrent();
585     CContextClient* client = context->client;
586     int serverSize = client->serverSize;
587     std::vector<CDomain*> domList = getDomains();
588     std::vector<CAxis*> axisList = getAxis();
589
590     // Some pre-calculations of global index on each element of current grid.
591     int nbElement = axis_domain_order.numElements();
592     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
593     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
594     std::vector<size_t> elementNGlobal(nbElement);
595     elementNGlobal[0] = 1;
596     size_t globalSize = 1;
597     for (int idx = 0; idx < nbElement; ++idx)
598     {
599       elementNGlobal[idx] = globalSize;
600       size_t elementSize;
601       size_t elementGlobalSize = 1;
602       if (2 == axis_domain_order(idx)) // This is domain
603       {
604         elementSize = domList[domainIdx]->i_index.numElements();
605         globalIndexElement[idx].resize(elementSize);
606         for (int jdx = 0; jdx < elementSize; ++jdx)
607         {
608           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
609         }
610         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
611         ++domainIdx;
612       }
613       else if (1 == axis_domain_order(idx))  // This is axis
614       {
615         elementSize = axisList[axisIdx]->index.numElements();
616         globalIndexElement[idx].resize(elementSize);
617         for (int jdx = 0; jdx < elementSize; ++jdx)
618         {
619           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
620         }
621         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
622         ++axisIdx;
623       }
624       else  // Of course, this is scalar
625       {
626         globalIndexElement[idx].resize(1);
627         globalIndexElement[idx](0) = 0;
628         elementGlobalSize = 1;
629       }
630       globalSize *= elementGlobalSize;
631     }
632
633     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
634     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
635     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
636     // Number of temporary distributed global index held by each client for each server
637     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
638     CArray<int,1> nbIndexOnServerTmp(serverSize);
639     for (int idx = 0; idx < nbElement; ++idx)
640     {
641       nbIndexOnServer = 0;
642       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
643       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
644       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
645       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
646       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
647       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
648                                                                    ite = globalIndexElementOnServerMap.end(), it;
649       for (it = itb; it != ite; ++it)
650       {
651         const std::vector<int>& tmp = it->second;
652         nbIndexOnServerTmp = 0;
653         for (int i = 0; i < tmp.size(); ++i)
654         {
655           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
656         }
657         nbIndexOnServer += nbIndexOnServerTmp;
658       }
659
660       for (int i = 0; i < serverSize; ++i)
661       {
662         if (0 != nbIndexOnServer(i))
663         {
664           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
665           elementOnServer[idx][i] = true;
666         }
667       }
668
669       nbIndexOnServer = 0;
670       for (it = itb; it != ite; ++it)
671       {
672         const std::vector<int>& tmp = it->second;
673         nbIndexOnServerTmp = 0;
674         for (int i = 0; i < tmp.size(); ++i)
675         {
676           if (0 == nbIndexOnServerTmp(tmp[i]))
677           {
678             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
679             ++nbIndexOnServerTmp(tmp[i]);
680           }
681         }
682         nbIndexOnServer += nbIndexOnServerTmp;
683       }
684     }
685
686    // Determine server which contain global source index
687    std::vector<bool> intersectedProc(serverSize, true);
688    for (int idx = 0; idx < nbElement; ++idx)
689    {
690      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
691                     intersectedProc.begin(), intersectedProc.begin(),
692                     std::logical_and<bool>());
693    }
694
695    std::vector<int> srcRank;
696    for (int idx = 0; idx < serverSize; ++idx)
697    {
698      if (intersectedProc[idx]) srcRank.push_back(idx);
699    }
700
701    // Compute the global index of grid from global index of each element.
702    for (int i = 0; i < srcRank.size(); ++i)
703    {
704      size_t ssize = 1;
705      int rankSrc = srcRank[i];
706      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
707      std::vector<size_t> currentIndex(nbElement,0);
708      for (int idx = 0; idx < nbElement; ++idx)
709      {
710        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
711        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
712      }
713      globalIndexOnServer[rankSrc].resize(ssize);
714
715      std::vector<int> idxLoop(nbElement,0);
716      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
717      size_t idx = 0;
718      while (idx < ssize)
719      {
720        for (int ind = 0; ind < nbElement; ++ind)
721        {
722          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
723          {
724            idxLoop[ind] = 0;
725            ++idxLoop[ind+1];
726          }
727
728          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
729        }
730
731        for (int ind = 0; ind < innnerLoopSize; ++ind)
732        {
733          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
734          size_t globalSrcIndex = 0;
735          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
736          {
737            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
738          }
739          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
740          ++idx;
741          ++idxLoop[0];
742        }
743      }
744    }
745   }
746   //----------------------------------------------------------------
747
748   CGrid* CGrid::createGrid(CDomain* domain)
749   {
750      std::vector<CDomain*> vecDom(1, domain);
751      std::vector<CAxis*> vecAxis;
752
753      return createGrid(vecDom, vecAxis);
754   }
755
756   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
757   {
758      std::vector<CDomain*> vecDom(1, domain);
759      std::vector<CAxis*> vecAxis(1, axis);
760
761      return createGrid(vecDom, vecAxis);
762   }
763
764   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
765                            const CArray<int,1>& axisDomainOrder)
766   {
767     std::vector<CScalar*> vecScalar;
768     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
769   }
770
771   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
772                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
773   {
774     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
775   }
776
777   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
778                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
779   {
780      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
781        ERROR("CGrid* CGrid::createGrid(...)",
782              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
783              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
784
785      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
786      grid->setDomainList(domains);
787      grid->setAxisList(axis);
788      grid->setScalarList(scalars);
789
790      // By default, domains are always the first elements of a grid
791      if (0 == axisDomainOrder.numElements())
792      {
793        int size = domains.size() + axis.size() + scalars.size();
794        int nb = 0;
795        grid->axis_domain_order.resize(size);
796        for (int i = 0; i < size; ++i)
797        {
798          if (i < domains.size()) {
799            grid->axis_domain_order(i) = 2;
800
801          }
802          else if ((scalars.size() < (size-nb)) < size) {
803            grid->axis_domain_order(i) = 1;
804          }
805          else
806            grid->axis_domain_order(i) = 0;
807          ++nb;
808        }
809      }
810      else
811      {
812        grid->axis_domain_order.resize(axisDomainOrder.numElements());
813        grid->axis_domain_order = axisDomainOrder;
814      }
815
816      grid->solveDomainAxisRefInheritance(true);
817
818      return grid;
819   }
820
821   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
822   {
823     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
824     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
825     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
826
827     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
828     {
829       CDomain* domain = CDomain::createDomain();
830       domain->duplicateAttributes(domainSrcTmp[idx]);
831       domain->duplicateTransformation(domainSrcTmp[idx]);
832       domain->solveRefInheritance(true);
833       domain->solveInheritanceTransformation();
834       domainSrc.push_back(domain);
835     }
836
837     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
838     {
839       CAxis* axis = CAxis::createAxis();
840       axis->duplicateAttributes(axisSrcTmp[idx]);
841       axis->duplicateTransformation(axisSrcTmp[idx]);
842       axis->solveRefInheritance(true);
843       axis->solveInheritanceTransformation();
844       axisSrc.push_back(axis);
845     }
846
847     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
848     {
849       CScalar* scalar = CScalar::createScalar();
850       scalar->duplicateAttributes(scalarSrcTmp[idx]);
851       scalar->duplicateTransformation(scalarSrcTmp[idx]);
852       scalar->solveRefInheritance(true);
853       scalar->solveInheritanceTransformation();
854       scalarSrc.push_back(scalar);
855     }
856
857      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
858
859      return grid;
860   }
861
862   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
863                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
864   {
865      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
866        ERROR("CGrid* CGrid::generateId(...)",
867              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
868              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
869
870      std::ostringstream id;
871
872      if (domains.empty() && axis.empty() && !scalars.empty())
873        id << "__scalar_";
874
875      if (0 != (domains.size() + axis.size() + scalars.size()))
876      {
877        id << "__grid";
878
879        if (0 == axisDomainOrder.numElements())
880        {
881          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
882          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
883          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
884        }
885        else
886        {
887          size_t iDomain = 0, iAxis = 0, iScalar = 0;
888          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
889          {
890            if (2 == axisDomainOrder(i))
891              id << "_" << domains[iDomain++]->getId();
892            else if (1 == axisDomainOrder(i))
893              id << "_" << axis[iAxis++]->getId();
894            else
895              id << "_" << scalars[iScalar++]->getId();
896          }
897        }
898
899        id << "__";
900      }
901
902      return id.str();
903   }
904
905   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
906   {
907     StdString idSrc  = gridSrc->getId();
908     StdString idDest = gridDest->getId();
909
910     std::ostringstream id;
911     id << idSrc << "__" << idDest;
912
913     return id.str();
914   }
915
916   //----------------------------------------------------------------
917
918   CDomainGroup* CGrid::getVirtualDomainGroup() const
919   {
920     return this->vDomainGroup_;
921   }
922
923   CAxisGroup* CGrid::getVirtualAxisGroup() const
924   {
925     return this->vAxisGroup_;
926   }
927
928   CScalarGroup* CGrid::getVirtualScalarGroup() const
929   {
930     return this->vScalarGroup_;
931   }
932
933   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
934   {
935     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
936     StdSize numElements = stored.numElements();
937     for (StdSize n = 0; n < numElements; ++n)
938     {
939       field[out_i(n)] = stored(n);
940     }
941   }
942
943   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
944   {
945     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
946     StdSize numElements = stored.numElements();
947     for (StdSize n = 0; n < numElements; ++n)
948     {
949       stored(n) = field[out_i(n)];
950     }
951   }
952
953   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
954   {
955     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
956     StdSize numElements = stored.numElements();
957     for (StdSize n = 0; n < numElements; ++n)
958     {
959       field[out_i(n)] = stored(n);
960     }
961   }
962
963   //----------------------------------------------------------------
964
965   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
966   {
967      const StdSize size = storeIndex_client.numElements();
968
969      stored.resize(size);
970      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
971   }
972
973   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
974   {
975      const StdSize size = storeIndex_client.numElements();
976
977      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
978   }
979
980  void CGrid::computeIndexScalarGrid()
981  {
982    CContext* context = CContext::getCurrent();
983    CContextClient* client=context->client;
984
985    storeIndex_client.resize(1);
986    storeIndex_client(0) = 0;
987
988    connectedServerRank_.clear();
989
990    if (0 == client->clientRank)
991    {
992      for (int rank = 0; rank < client->serverSize; ++rank)
993      {
994        connectedServerRank_.push_back(rank);
995        connectedDataSize_[rank] = 1;
996        nbSenders[rank] = 1;
997      }
998    }
999    isDataDistributed_ = false;
1000  }
1001
1002  void CGrid::computeCompressedIndex()
1003  {
1004    std::map<size_t, size_t> indexes;
1005
1006    {
1007      std::map<int, CArray<size_t,1> >::const_iterator it = outIndexFromClient.begin();
1008      std::map<int, CArray<size_t,1> >::const_iterator itEnd = outIndexFromClient.end();
1009      for (; it != itEnd; ++it)
1010      {
1011        for (int i = 0; i < it->second.numElements(); ++i)
1012          indexes.insert(std::make_pair(it->second(i), 0));
1013
1014        compressedOutIndexFromClient[it->first].resize(it->second.numElements());
1015      }
1016    }
1017
1018    {
1019      std::map<size_t, size_t>::iterator it = indexes.begin();
1020      std::map<size_t, size_t>::iterator itEnd = indexes.end();
1021      for (size_t i = 0; it != itEnd; ++it, ++i)
1022        it->second = i;
1023    }
1024
1025    {
1026      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
1027      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
1028      for (; it != itEnd; ++it)
1029      {
1030        const CArray<size_t,1>& outIndex = outIndexFromClient[it->first];
1031        for (int i = 0; i < it->second.numElements(); ++i)
1032          it->second(i) = indexes[outIndex(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  /*
1326     Compute on the fly the global dimension of a grid with its elements
1327     \param[in/out] globalDim global dimension of grid
1328     \param[in] domains list of its domains
1329     \param[in] axiss list of its axis
1330     \param[in] scalars list of its scalars
1331     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1332     \return The dimension of which we do distribution (often for server)
1333  */
1334  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1335                                        const std::vector<CDomain*> domains,
1336                                        const std::vector<CAxis*> axis,
1337                                        const std::vector<CScalar*> scalars,
1338                                        const CArray<int,1>& axisDomainOrder)
1339  {
1340    globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1341    int positionDimensionDistributed = 1;
1342    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1343    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1344    {
1345      if (2 == axisDomainOrder(i))
1346      {
1347        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1348        {
1349          positionDimensionDistributed = idx;
1350        }
1351        else
1352        {
1353          positionDimensionDistributed = idx +1;
1354        }
1355
1356        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
1357        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
1358
1359        ++idxDomain;
1360        idx += 2;
1361      }
1362      else if (1 == axisDomainOrder(i))
1363      {
1364        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
1365        ++idxAxis;
1366        ++idx;
1367      }
1368      else
1369      {
1370        globalDim[idx] = 1;
1371        ++idxScalar;
1372        ++idx;
1373      }
1374    }
1375
1376    return positionDimensionDistributed;
1377  }
1378
1379  // Retrieve the global dimension of grid
1380  std::vector<int> CGrid::getGlobalDimension()
1381  {
1382    std::vector<int> globalDim;
1383    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
1384
1385    return globalDim;
1386  }
1387
1388  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
1389  int CGrid::getDistributedDimension()
1390  {
1391    std::vector<int> globalDim;
1392    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
1393  }
1394
1395  bool CGrid::isScalarGrid() const
1396  {
1397    return (axisList_.empty() && domList_.empty());
1398  }
1399
1400  /*!
1401    Verify whether one server need to write data
1402    There are some cases on which one server has nodata to write. For example, when we
1403    just only want to zoom on a domain.
1404  */
1405  bool CGrid::doGridHaveDataToWrite()
1406  {
1407     return (0 != writtenDataSize_);
1408  }
1409
1410  /*!
1411    Return size of data which is written on each server
1412    Whatever dimension of a grid, data which are written on server must be presented as
1413    an one dimension array.
1414    \return size of data written on server
1415  */
1416  size_t CGrid::getWrittenDataSize() const
1417  {
1418    return writtenDataSize_;
1419  }
1420
1421  /*!
1422    Returns the number of indexes written by each server.
1423    \return the number of indexes written by each server
1424  */
1425  int CGrid::getNumberWrittenIndexes() const
1426  {
1427    return numberWrittenIndexes_;
1428  }
1429
1430  /*!
1431    Returns the total number of indexes written by the servers.
1432    \return the total number of indexes written by the servers
1433  */
1434  int CGrid::getTotalNumberWrittenIndexes() const
1435  {
1436    return totalNumberWrittenIndexes_;
1437  }
1438
1439  /*!
1440    Returns the offset of indexes written by each server.
1441    \return the offset of indexes written by each server
1442  */
1443  int CGrid::getOffsetWrittenIndexes() const
1444  {
1445    return offsetWrittenIndexes_;
1446  }
1447
1448  CDistributionServer* CGrid::getDistributionServer()
1449  {
1450    return serverDistribution_;
1451  }
1452
1453  CDistributionClient* CGrid::getDistributionClient()
1454  {
1455    return clientDistribution_;
1456  }
1457
1458  bool CGrid::doGridHaveDataDistributed()
1459  {
1460    if (isScalarGrid()) return false;
1461    else
1462      return isDataDistributed_;
1463  }
1464
1465   /*!
1466   \brief Dispatch event received from client
1467      Whenever a message is received in buffer of server, it will be processed depending on
1468   its event type. A new event type should be added in the switch list to make sure
1469   it processed on server side.
1470   \param [in] event: Received message
1471   */
1472  bool CGrid::dispatchEvent(CEventServer& event)
1473  {
1474
1475    if (SuperClass::dispatchEvent(event)) return true;
1476    else
1477    {
1478      switch(event.type)
1479      {
1480        case EVENT_ID_INDEX :
1481          recvIndex(event);
1482          return true;
1483          break;
1484
1485         case EVENT_ID_ADD_DOMAIN :
1486           recvAddDomain(event);
1487           return true;
1488           break;
1489
1490         case EVENT_ID_ADD_AXIS :
1491           recvAddAxis(event);
1492           return true;
1493           break;
1494
1495         case EVENT_ID_ADD_SCALAR :
1496           recvAddScalar(event);
1497           return true;
1498           break;
1499        default :
1500          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1501                << "Unknown Event");
1502          return false;
1503      }
1504    }
1505  }
1506
1507   ///---------------------------------------------------------------
1508
1509   CDomain* CGrid::addDomain(const std::string& id)
1510   {
1511     order_.push_back(2);
1512     axis_domain_order.resize(order_.size());
1513     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1514     return vDomainGroup_->createChild(id);
1515   }
1516
1517   CAxis* CGrid::addAxis(const std::string& id)
1518   {
1519     order_.push_back(1);
1520     axis_domain_order.resize(order_.size());
1521     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1522     return vAxisGroup_->createChild(id);
1523   }
1524
1525   CScalar* CGrid::addScalar(const std::string& id)
1526   {
1527     order_.push_back(0);
1528     axis_domain_order.resize(order_.size());
1529     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1530     return vScalarGroup_->createChild(id);
1531   }
1532
1533   //! Change virtual field group to a new one
1534   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1535   {
1536      this->vDomainGroup_ = newVDomainGroup;
1537   }
1538
1539   //! Change virtual variable group to new one
1540   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1541   {
1542      this->vAxisGroup_ = newVAxisGroup;
1543   }
1544
1545   //! Change virtual variable group to new one
1546   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1547   {
1548      this->vScalarGroup_ = newVScalarGroup;
1549   }
1550
1551   /*!
1552   \brief Send a message to create a domain on server side
1553   \param[in] id String identity of domain that will be created on server
1554   */
1555   void CGrid::sendAddDomain(const string& id)
1556   {
1557    CContext* context=CContext::getCurrent();
1558
1559    if (! context->hasServer )
1560    {
1561       CContextClient* client=context->client;
1562
1563       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1564       if (client->isServerLeader())
1565       {
1566         CMessage msg;
1567         msg<<this->getId();
1568         msg<<id;
1569         const std::list<int>& ranks = client->getRanksServerLeader();
1570         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1571           event.push(*itRank,1,msg);
1572         client->sendEvent(event);
1573       }
1574       else client->sendEvent(event);
1575    }
1576   }
1577
1578   /*!
1579   \brief Send a message to create an axis on server side
1580   \param[in] id String identity of axis that will be created on server
1581   */
1582   void CGrid::sendAddAxis(const string& id)
1583   {
1584    CContext* context=CContext::getCurrent();
1585
1586    if (! context->hasServer )
1587    {
1588       CContextClient* client=context->client;
1589
1590       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1591       if (client->isServerLeader())
1592       {
1593         CMessage msg;
1594         msg<<this->getId();
1595         msg<<id;
1596         const std::list<int>& ranks = client->getRanksServerLeader();
1597         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1598           event.push(*itRank,1,msg);
1599         client->sendEvent(event);
1600       }
1601       else client->sendEvent(event);
1602    }
1603   }
1604
1605   /*!
1606   \brief Send a message to create a scalar on server side
1607   \param[in] id String identity of scalar that will be created on server
1608   */
1609   void CGrid::sendAddScalar(const string& id)
1610   {
1611    CContext* context=CContext::getCurrent();
1612
1613    if (! context->hasServer )
1614    {
1615       CContextClient* client=context->client;
1616
1617       CEventClient event(this->getType(),EVENT_ID_ADD_SCALAR);
1618       if (client->isServerLeader())
1619       {
1620         CMessage msg;
1621         msg<<this->getId();
1622         msg<<id;
1623         const std::list<int>& ranks = client->getRanksServerLeader();
1624         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1625           event.push(*itRank,1,msg);
1626         client->sendEvent(event);
1627       }
1628       else client->sendEvent(event);
1629    }
1630   }
1631
1632   /*!
1633   \brief Receive a message annoucing the creation of a domain on server side
1634   \param[in] event Received event
1635   */
1636   void CGrid::recvAddDomain(CEventServer& event)
1637   {
1638
1639      CBufferIn* buffer = event.subEvents.begin()->buffer;
1640      string id;
1641      *buffer >> id;
1642      get(id)->recvAddDomain(*buffer);
1643   }
1644
1645   /*!
1646   \brief Receive a message annoucing the creation of a domain on server side
1647   \param[in] buffer Buffer containing message
1648   */
1649   void CGrid::recvAddDomain(CBufferIn& buffer)
1650   {
1651      string id;
1652      buffer >> id;
1653      addDomain(id);
1654   }
1655
1656   /*!
1657   \brief Receive a message annoucing the creation of an axis on server side
1658   \param[in] event Received event
1659   */
1660   void CGrid::recvAddAxis(CEventServer& event)
1661   {
1662
1663      CBufferIn* buffer = event.subEvents.begin()->buffer;
1664      string id;
1665      *buffer >> id;
1666      get(id)->recvAddAxis(*buffer);
1667   }
1668
1669   /*!
1670   \brief Receive a message annoucing the creation of an axis on server side
1671   \param[in] buffer Buffer containing message
1672   */
1673   void CGrid::recvAddAxis(CBufferIn& buffer)
1674   {
1675      string id;
1676      buffer >> id;
1677      addAxis(id);
1678   }
1679
1680   /*!
1681   \brief Receive a message annoucing the creation of an scalar on server side
1682   \param[in] event Received event
1683   */
1684   void CGrid::recvAddScalar(CEventServer& event)
1685   {
1686
1687      CBufferIn* buffer = event.subEvents.begin()->buffer;
1688      string id;
1689      *buffer >> id;
1690      get(id)->recvAddScalar(*buffer);
1691   }
1692
1693   /*!
1694   \brief Receive a message annoucing the creation of an scalar on server side
1695   \param[in] buffer Buffer containing message
1696   */
1697   void CGrid::recvAddScalar(CBufferIn& buffer)
1698   {
1699      string id;
1700      buffer >> id;
1701      addScalar(id);
1702   }
1703
1704  /*!
1705  \brief Solve domain and axis references
1706  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1707  all attributes from their parents, they should be processed with this function
1708  \param[in] apply inherit all attributes of parents (true)
1709  */
1710  void CGrid::solveDomainAxisRefInheritance(bool apply)
1711  {
1712    CContext* context = CContext::getCurrent();
1713    unsigned int vecSize, i;
1714    std::vector<StdString>::iterator it, itE;
1715    setDomainList();
1716    it = domList_.begin(); itE = domList_.end();
1717    for (; it != itE; ++it)
1718    {
1719      CDomain* pDom = CDomain::get(*it);
1720      if (context->hasClient)
1721      {
1722        pDom->solveRefInheritance(apply);
1723        pDom->solveInheritanceTransformation();
1724      }
1725    }
1726
1727    setAxisList();
1728    it = axisList_.begin(); itE = axisList_.end();
1729    for (; it != itE; ++it)
1730    {
1731      CAxis* pAxis = CAxis::get(*it);
1732      if (context->hasClient)
1733      {
1734        pAxis->solveRefInheritance(apply);
1735        pAxis->solveInheritanceTransformation();
1736      }
1737    }
1738
1739    setScalarList();
1740    it = scalarList_.begin(); itE = scalarList_.end();
1741    for (; it != itE; ++it)
1742    {
1743      CScalar* pScalar = CScalar::get(*it);
1744      if (context->hasClient)
1745      {
1746        pScalar->solveRefInheritance(apply);
1747        pScalar->solveInheritanceTransformation();
1748      }
1749    }
1750  }
1751
1752  bool CGrid::isTransformed()
1753  {
1754    return isTransformed_;
1755  }
1756
1757  void CGrid::setTransformed()
1758  {
1759    isTransformed_ = true;
1760  }
1761
1762  CGridTransformation* CGrid::getTransformations()
1763  {
1764    return transformations_;
1765  }
1766
1767  void CGrid::addTransGridSource(CGrid* gridSrc)
1768  {
1769    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1770      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1771  }
1772
1773  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1774  {
1775    return gridSrc_;
1776  }
1777
1778  /*!
1779     Complete all the necessary (and lacking) attributes of a grid
1780     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1781  */
1782  void CGrid::completeGrid(CGrid* transformGridSrc)
1783  {
1784    if (0 != transformGridSrc)
1785    {
1786      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1787      {
1788        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1789             << "Two grids have different number of elements. " << std::endl
1790             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1791             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1792      }
1793    }
1794
1795    if (isGenerated()) return;
1796    setGenerated();
1797
1798    CGridGenerate gridGenerate(this, transformGridSrc);
1799    gridGenerate.completeGrid();
1800  }
1801
1802  bool CGrid::isGenerated()
1803  {
1804    return isGenerated_;
1805  }
1806
1807  void CGrid::setGenerated()
1808  {
1809    isGenerated_ = true;
1810  }
1811
1812  void CGrid::transformGrid(CGrid* transformGridSrc)
1813  {
1814    if (!transformGridSrc)
1815      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1816            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1817
1818    if (isTransformed()) return;
1819    setTransformed();
1820    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1821    {
1822      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1823           << "Two grids have different number of elements. " << std::endl
1824           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1825           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1826    }
1827    else
1828    {
1829    }
1830
1831    transformations_ = new CGridTransformation(this, transformGridSrc);
1832    transformations_->computeAll();
1833    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1834
1835    // Ok, now need to compute index of grid source
1836    transformGridSrc->checkMaskIndex(false);
1837  }
1838
1839  bool CGrid::hasTransform()
1840  {
1841    if (hasTransform_) return hasTransform_;
1842
1843    std::vector<CDomain*> domList = getDomains();
1844    std::vector<CAxis*> axisList = getAxis();
1845    std::vector<CScalar*> scalarList = getScalars();
1846
1847    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
1848    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
1849    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
1850
1851    return hasTransform_;
1852  }
1853
1854  /*!
1855  \brief Get the list of domain pointers
1856  \return list of domain pointers
1857  */
1858  std::vector<CDomain*> CGrid::getDomains()
1859  {
1860    std::vector<CDomain*> domList;
1861    if (!domList_.empty())
1862    {
1863      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1864    }
1865    return domList;
1866  }
1867
1868  /*!
1869  \brief Get the list of  axis pointers
1870  \return list of axis pointers
1871  */
1872  std::vector<CAxis*> CGrid::getAxis()
1873  {
1874    std::vector<CAxis*> aList;
1875    if (!axisList_.empty())
1876      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1877
1878    return aList;
1879  }
1880
1881  /*!
1882  \brief Get the list of  axis pointers
1883  \return list of axis pointers
1884  */
1885  std::vector<CScalar*> CGrid::getScalars()
1886  {
1887    std::vector<CScalar*> sList;
1888    if (!scalarList_.empty())
1889      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
1890
1891    return sList;
1892  }
1893
1894  /*!
1895  \brief Get domain pointer with index
1896  \return domain pointer
1897  */
1898  CDomain* CGrid::getDomain(int domainIndex)
1899  {
1900    std::vector<CDomain*> domainListP = this->getDomains();
1901    if (domainListP.empty())
1902    {
1903      ERROR("CGrid::getDomain(int domainIndex)",
1904            << "No domain associated to this grid. " << std::endl
1905            << "Grid id = " << this->getId());
1906    }
1907
1908    if (domainIndex >= domainListP.size() || (domainIndex < 0))
1909      ERROR("CGrid::getDomain(int domainIndex)",
1910            << "Domain with the index doesn't exist " << std::endl
1911            << "Grid id = " << this->getId() << std::endl
1912            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
1913
1914    return domainListP[domainIndex];
1915  }
1916
1917  /*!
1918  \brief Get the axis pointer with index
1919  \return axis pointer
1920  */
1921  CAxis* CGrid::getAxis(int axisIndex)
1922  {
1923    std::vector<CAxis*> axisListP = this->getAxis();
1924    if (axisListP.empty())
1925    {
1926      ERROR("CGrid::getDomain(int axisIndex)",
1927            << "No axis associated to this grid. " << std::endl
1928            << "Grid id = " << this->getId());
1929    }
1930
1931    if (axisIndex >= axisListP.size() || (axisIndex < 0))
1932      ERROR("CGrid::getDomain(int axisIndex)",
1933            << "Domain with the index doesn't exist " << std::endl
1934            << "Grid id = " << this->getId() << std::endl
1935            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
1936
1937    return axisListP[axisIndex];
1938  }
1939
1940  /*!
1941  \brief Get the a scalar pointer
1942  \return scalar pointer
1943  */
1944  CScalar* CGrid::getScalar(int scalarIndex)
1945  {
1946    std::vector<CScalar*> scalarListP = this->getScalars();
1947    if (scalarListP.empty())
1948    {
1949      ERROR("CGrid::getScalar(int scalarIndex)",
1950            << "No scalar associated to this grid. " << std::endl
1951            << "Grid id = " << this->getId());
1952    }
1953
1954    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
1955      ERROR("CGrid::getScalar(int scalarIndex)",
1956            << "Scalar with the index doesn't exist " << std::endl
1957            << "Grid id = " << this->getId() << std::endl
1958            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
1959
1960    return scalarListP[scalarIndex];
1961  }
1962
1963  /*!
1964  \brief Set domain(s) of a grid from a list
1965  \param[in] domains list of domains
1966  */
1967  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1968  {
1969    if (isDomListSet) return;
1970    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1971    if (!domains.empty() && domList.empty())
1972    {
1973      for (int i = 0; i < domains.size(); ++i)
1974        this->getVirtualDomainGroup()->addChild(domains[i]);
1975      domList = this->getVirtualDomainGroup()->getAllChildren();
1976    }
1977
1978    if (!domList.empty())
1979    {
1980      int sizeDom = domList.size();
1981      domList_.resize(sizeDom);
1982      for (int i = 0; i < sizeDom; ++i)
1983      {
1984        domList_[i] = domList[i]->getId();
1985      }
1986      isDomListSet = true;
1987    }
1988
1989  }
1990
1991  /*!
1992  \brief Set axis(s) of a grid from a list
1993  \param[in] axis list of axis
1994  */
1995  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1996  {
1997    if (isAxisListSet) return;
1998    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1999    if (!axis.empty() && aList.empty())
2000    {
2001      for (int i = 0; i < axis.size(); ++i)
2002        this->getVirtualAxisGroup()->addChild(axis[i]);
2003      aList = this->getVirtualAxisGroup()->getAllChildren();
2004    }
2005
2006    if (!aList.empty())
2007    {
2008      int sizeAxis = aList.size();
2009      axisList_.resize(sizeAxis);
2010      for (int i = 0; i < sizeAxis; ++i)
2011      {
2012        axisList_[i] = aList[i]->getId();
2013      }
2014      isAxisListSet = true;
2015    }
2016  }
2017
2018  /*!
2019  \brief Set scalar(s) of a grid from a list
2020  \param[in] scalars list of scalars
2021  */
2022  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
2023  {
2024    if (isScalarListSet) return;
2025    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2026    if (!scalars.empty() && sList.empty())
2027    {
2028      for (int i = 0; i < scalars.size(); ++i)
2029        this->getVirtualScalarGroup()->addChild(scalars[i]);
2030      sList = this->getVirtualScalarGroup()->getAllChildren();
2031    }
2032
2033    if (!sList.empty())
2034    {
2035      int sizeScalar = sList.size();
2036      scalarList_.resize(sizeScalar);
2037      for (int i = 0; i < sizeScalar; ++i)
2038      {
2039        scalarList_[i] = sList[i]->getId();
2040      }
2041      isScalarListSet = true;
2042    }
2043  }
2044
2045  /*!
2046  \brief Get list of id of domains
2047  \return id list of domains
2048  */
2049  std::vector<StdString> CGrid::getDomainList()
2050  {
2051    setDomainList();
2052    return domList_;
2053  }
2054
2055  /*!
2056  \brief Get list of id of axis
2057  \return id list of axis
2058  */
2059  std::vector<StdString> CGrid::getAxisList()
2060  {
2061    setAxisList();
2062    return axisList_;
2063  }
2064
2065  /*!
2066  \brief Get list of id of scalar
2067  \return id list of scalar
2068  */
2069  std::vector<StdString> CGrid::getScalarList()
2070  {
2071    setScalarList();
2072    return scalarList_;
2073  }
2074
2075  /*!
2076    Send all attributes of domains from client to server
2077  */
2078  void CGrid::sendAllDomains()
2079  {
2080    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2081    int dSize = domList.size();
2082    for (int i = 0; i < dSize; ++i)
2083    {
2084      sendAddDomain(domList[i]->getId());
2085      domList[i]->sendAllAttributesToServer();
2086    }
2087  }
2088
2089  /*!
2090    Send all attributes of axis from client to server
2091  */
2092  void CGrid::sendAllAxis()
2093  {
2094    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2095    int aSize = aList.size();
2096
2097    for (int i = 0; i < aSize; ++i)
2098    {
2099      sendAddAxis(aList[i]->getId());
2100      aList[i]->sendAllAttributesToServer();
2101    }
2102  }
2103
2104  /*!
2105    Send all attributes of scalars from client to server
2106  */
2107  void CGrid::sendAllScalars()
2108  {
2109    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2110    int sSize = sList.size();
2111
2112    for (int i = 0; i < sSize; ++i)
2113    {
2114      sendAddScalar(sList[i]->getId());
2115      sList[i]->sendAllAttributesToServer();
2116    }
2117  }
2118
2119  /*!
2120    Parse a grid, for now, it contains only domain, axis and scalar
2121  */
2122  void CGrid::parse(xml::CXMLNode& node)
2123  {
2124    SuperClass::parse(node);
2125
2126    if (node.goToChildElement())
2127    {
2128      StdString domainName("domain");
2129      StdString axisName("axis");
2130      StdString scalarName("scalar");
2131      do
2132      {
2133        if (node.getElementName() == domainName) {
2134          order_.push_back(2);
2135          this->getVirtualDomainGroup()->parseChild(node);
2136        }
2137        if (node.getElementName() == axisName) {
2138          order_.push_back(1);
2139          this->getVirtualAxisGroup()->parseChild(node);
2140        }
2141        if (node.getElementName() == scalarName) {
2142          order_.push_back(0);
2143          this->getVirtualScalarGroup()->parseChild(node);
2144        }
2145      } while (node.goToNextElement());
2146      node.goToParentElement();
2147    }
2148
2149    if (!order_.empty())
2150    {
2151      int sizeOrd = order_.size();
2152      axis_domain_order.resize(sizeOrd);
2153      for (int i = 0; i < sizeOrd; ++i)
2154      {
2155        axis_domain_order(i) = order_[i];
2156      }
2157    }
2158
2159    setDomainList();
2160    setAxisList();
2161    setScalarList();
2162   }
2163} // namespace xios
Note: See TracBrowser for help on using the repository browser.