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

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

branch merged with trunk @1200

  • 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: 71.3 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        std::vector<CArray<int,1> > globalZoomIndex(numElement);
1256        for (int i = 0; i < numElement; ++i)
1257        {
1258          if (2 == axis_domain_order(i)) //domain
1259          {
1260            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
1261            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
1262            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
1263            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1264
1265            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
1266            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
1267            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
1268            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1269
1270            {
1271              int count = 0;
1272              globalZoomIndex[i].resize(nZoomSize[indexMap[i]]*nZoomSize[indexMap[i]+1]);
1273              for (int jdx = 0; jdx < nZoomSize[indexMap[i]+1]; ++jdx)
1274                for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)               
1275                {
1276                  globalZoomIndex[i](count) = (nZoomBegin[indexMap[i]] + idx) + (nZoomBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
1277                  ++count;
1278                }
1279            }
1280            ++domainId;
1281          }
1282          else if (1 == axis_domain_order(i)) // axis
1283          {
1284            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1285            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1286            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin_srv;
1287            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1288            if (!axisList[axisId]->global_zoom_index.isEmpty())
1289            {
1290              globalZoomIndex[i].reference(axisList[axisId]->zoom_index_srv);               
1291            }
1292            else
1293            {
1294              globalZoomIndex[i].resize(nZoomSize[indexMap[i]]);
1295              for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)
1296                globalZoomIndex[i](idx) = nZoomBegin[indexMap[i]] + idx;
1297            }
1298           
1299            ++axisId;
1300          }
1301          else // scalar
1302          {
1303            nZoomBegin[indexMap[i]] = 0;
1304            nZoomSize[indexMap[i]]  = 1;
1305            nZoomBeginGlobal[indexMap[i]] = 0;
1306            nGlob[indexMap[i]] = 1;
1307            globalZoomIndex[i].resize(1);
1308            globalZoomIndex[i](0) = 0;
1309            ++scalarId;
1310          }
1311        }
1312        dataSize = 1;
1313        for (int i = 0; i < nZoomSize.size(); ++i)
1314          dataSize *= nZoomSize[i];
1315
1316/*        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1317                                                      nZoomBeginGlobal, nGlob);*/
1318        serverDistribution_ = new CDistributionServer(server->intraCommRank, 
1319                                                      globalZoomIndex, axis_domain_order,
1320                                                      nZoomBegin, nZoomSize, nZoomBeginGlobal, nGlob);
1321      }
1322
1323      CArray<size_t,1> outIndex;
1324      buffer >> outIndex;
1325      if (isDataDistributed_)
1326        serverDistribution_->computeLocalIndex(outIndex);
1327      else
1328      {
1329        dataSize = outIndex.numElements();
1330        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
1331      }
1332      writtenDataSize_ += dataSize;
1333     
1334      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1335      connectedDataSize_[rank] = outIndex.numElements();
1336      numberWrittenIndexes_ += outIndex.numElements();
1337    }
1338
1339    // if (isScalarGrid()) return;
1340
1341    if (isDataDistributed_)
1342    {
1343      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1344      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1345      offsetWrittenIndexes_ -= numberWrittenIndexes_;
1346    }
1347    else
1348      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1349
1350    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1351  }
1352
1353  /*
1354     Compute on the fly the global dimension of a grid with its elements
1355     \param[in/out] globalDim global dimension of grid
1356     \param[in] domains list of its domains
1357     \param[in] axiss list of its axis
1358     \param[in] scalars list of its scalars
1359     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1360     \return The dimension of which we do distribution (often for server)
1361  */
1362  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1363                                        const std::vector<CDomain*> domains,
1364                                        const std::vector<CAxis*> axis,
1365                                        const std::vector<CScalar*> scalars,
1366                                        const CArray<int,1>& axisDomainOrder)
1367  {
1368    globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1369    int positionDimensionDistributed = 1;
1370    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1371    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1372    {
1373      if (2 == axisDomainOrder(i))
1374      {
1375        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1376        {
1377          positionDimensionDistributed = idx;
1378        }
1379        else
1380        {
1381          positionDimensionDistributed = idx +1;
1382        }
1383
1384        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
1385        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
1386
1387        ++idxDomain;
1388        idx += 2;
1389      }
1390      else if (1 == axisDomainOrder(i))
1391      {
1392        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
1393        ++idxAxis;
1394        ++idx;
1395      }
1396      else
1397      {
1398        globalDim[idx] = 1;
1399        ++idxScalar;
1400        ++idx;
1401      }
1402    }
1403
1404    return positionDimensionDistributed;
1405  }
1406
1407  // Retrieve the global dimension of grid
1408  std::vector<int> CGrid::getGlobalDimension()
1409  {
1410    std::vector<int> globalDim;
1411    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
1412
1413    return globalDim;
1414  }
1415
1416  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
1417  int CGrid::getDistributedDimension()
1418  {
1419    std::vector<int> globalDim;
1420    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
1421  }
1422
1423  bool CGrid::isScalarGrid() const
1424  {
1425    return (axisList_.empty() && domList_.empty());
1426  }
1427
1428  /*!
1429    Verify whether one server need to write data
1430    There are some cases on which one server has nodata to write. For example, when we
1431    just only want to zoom on a domain.
1432  */
1433  bool CGrid::doGridHaveDataToWrite()
1434  {
1435     return (0 != writtenDataSize_);
1436  }
1437
1438  /*!
1439    Return size of data which is written on each server
1440    Whatever dimension of a grid, data which are written on server must be presented as
1441    an one dimension array.
1442    \return size of data written on server
1443  */
1444  size_t CGrid::getWrittenDataSize() const
1445  {
1446    return writtenDataSize_;
1447  }
1448
1449  /*!
1450    Returns the number of indexes written by each server.
1451    \return the number of indexes written by each server
1452  */
1453  int CGrid::getNumberWrittenIndexes() const
1454  {
1455    return numberWrittenIndexes_;
1456  }
1457
1458  /*!
1459    Returns the total number of indexes written by the servers.
1460    \return the total number of indexes written by the servers
1461  */
1462  int CGrid::getTotalNumberWrittenIndexes() const
1463  {
1464    return totalNumberWrittenIndexes_;
1465  }
1466
1467  /*!
1468    Returns the offset of indexes written by each server.
1469    \return the offset of indexes written by each server
1470  */
1471  int CGrid::getOffsetWrittenIndexes() const
1472  {
1473    return offsetWrittenIndexes_;
1474  }
1475
1476  CDistributionServer* CGrid::getDistributionServer()
1477  {
1478    return serverDistribution_;
1479  }
1480
1481  CDistributionClient* CGrid::getDistributionClient()
1482  {
1483    return clientDistribution_;
1484  }
1485
1486  bool CGrid::doGridHaveDataDistributed()
1487  {
1488    if (isScalarGrid()) return false;
1489    else
1490      return isDataDistributed_;
1491  }
1492
1493   /*!
1494   \brief Dispatch event received from client
1495      Whenever a message is received in buffer of server, it will be processed depending on
1496   its event type. A new event type should be added in the switch list to make sure
1497   it processed on server side.
1498   \param [in] event: Received message
1499   */
1500  bool CGrid::dispatchEvent(CEventServer& event)
1501  {
1502
1503    if (SuperClass::dispatchEvent(event)) return true;
1504    else
1505    {
1506      switch(event.type)
1507      {
1508        case EVENT_ID_INDEX :
1509          recvIndex(event);
1510          return true;
1511          break;
1512
1513         case EVENT_ID_ADD_DOMAIN :
1514           recvAddDomain(event);
1515           return true;
1516           break;
1517
1518         case EVENT_ID_ADD_AXIS :
1519           recvAddAxis(event);
1520           return true;
1521           break;
1522
1523         case EVENT_ID_ADD_SCALAR :
1524           recvAddScalar(event);
1525           return true;
1526           break;
1527        default :
1528          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1529                << "Unknown Event");
1530          return false;
1531      }
1532    }
1533  }
1534
1535   ///---------------------------------------------------------------
1536
1537   CDomain* CGrid::addDomain(const std::string& id)
1538   {
1539     order_.push_back(2);
1540     axis_domain_order.resize(order_.size());
1541     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1542     return vDomainGroup_->createChild(id);
1543   }
1544
1545   CAxis* CGrid::addAxis(const std::string& id)
1546   {
1547     order_.push_back(1);
1548     axis_domain_order.resize(order_.size());
1549     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1550     return vAxisGroup_->createChild(id);
1551   }
1552
1553   CScalar* CGrid::addScalar(const std::string& id)
1554   {
1555     order_.push_back(0);
1556     axis_domain_order.resize(order_.size());
1557     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1558     return vScalarGroup_->createChild(id);
1559   }
1560
1561   //! Change virtual field group to a new one
1562   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1563   {
1564      this->vDomainGroup_ = newVDomainGroup;
1565   }
1566
1567   //! Change virtual variable group to new one
1568   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1569   {
1570      this->vAxisGroup_ = newVAxisGroup;
1571   }
1572
1573   //! Change virtual variable group to new one
1574   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1575   {
1576      this->vScalarGroup_ = newVScalarGroup;
1577   }
1578
1579   /*!
1580   \brief Send a message to create a domain on server side
1581   \param[in] id String identity of domain that will be created on server
1582   */
1583   void CGrid::sendAddDomain(const string& id)
1584   {
1585    CContext* context=CContext::getCurrent();
1586
1587    if (! context->hasServer )
1588    {
1589       CContextClient* client=context->client;
1590
1591       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1592       if (client->isServerLeader())
1593       {
1594         CMessage msg;
1595         msg<<this->getId();
1596         msg<<id;
1597         const std::list<int>& ranks = client->getRanksServerLeader();
1598         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1599           event.push(*itRank,1,msg);
1600         client->sendEvent(event);
1601       }
1602       else client->sendEvent(event);
1603    }
1604   }
1605
1606   /*!
1607   \brief Send a message to create an axis on server side
1608   \param[in] id String identity of axis that will be created on server
1609   */
1610   void CGrid::sendAddAxis(const string& id)
1611   {
1612    CContext* context=CContext::getCurrent();
1613
1614    if (! context->hasServer )
1615    {
1616       CContextClient* client=context->client;
1617
1618       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1619       if (client->isServerLeader())
1620       {
1621         CMessage msg;
1622         msg<<this->getId();
1623         msg<<id;
1624         const std::list<int>& ranks = client->getRanksServerLeader();
1625         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1626           event.push(*itRank,1,msg);
1627         client->sendEvent(event);
1628       }
1629       else client->sendEvent(event);
1630    }
1631   }
1632
1633   /*!
1634   \brief Send a message to create a scalar on server side
1635   \param[in] id String identity of scalar that will be created on server
1636   */
1637   void CGrid::sendAddScalar(const string& id)
1638   {
1639    CContext* context=CContext::getCurrent();
1640
1641    if (! context->hasServer )
1642    {
1643       CContextClient* client=context->client;
1644
1645       CEventClient event(this->getType(),EVENT_ID_ADD_SCALAR);
1646       if (client->isServerLeader())
1647       {
1648         CMessage msg;
1649         msg<<this->getId();
1650         msg<<id;
1651         const std::list<int>& ranks = client->getRanksServerLeader();
1652         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1653           event.push(*itRank,1,msg);
1654         client->sendEvent(event);
1655       }
1656       else client->sendEvent(event);
1657    }
1658   }
1659
1660   /*!
1661   \brief Receive a message annoucing the creation of a domain on server side
1662   \param[in] event Received event
1663   */
1664   void CGrid::recvAddDomain(CEventServer& event)
1665   {
1666
1667      CBufferIn* buffer = event.subEvents.begin()->buffer;
1668      string id;
1669      *buffer >> id;
1670      get(id)->recvAddDomain(*buffer);
1671   }
1672
1673   /*!
1674   \brief Receive a message annoucing the creation of a domain on server side
1675   \param[in] buffer Buffer containing message
1676   */
1677   void CGrid::recvAddDomain(CBufferIn& buffer)
1678   {
1679      string id;
1680      buffer >> id;
1681      addDomain(id);
1682   }
1683
1684   /*!
1685   \brief Receive a message annoucing the creation of an axis on server side
1686   \param[in] event Received event
1687   */
1688   void CGrid::recvAddAxis(CEventServer& event)
1689   {
1690
1691      CBufferIn* buffer = event.subEvents.begin()->buffer;
1692      string id;
1693      *buffer >> id;
1694      get(id)->recvAddAxis(*buffer);
1695   }
1696
1697   /*!
1698   \brief Receive a message annoucing the creation of an axis on server side
1699   \param[in] buffer Buffer containing message
1700   */
1701   void CGrid::recvAddAxis(CBufferIn& buffer)
1702   {
1703      string id;
1704      buffer >> id;
1705      addAxis(id);
1706   }
1707
1708   /*!
1709   \brief Receive a message annoucing the creation of an scalar on server side
1710   \param[in] event Received event
1711   */
1712   void CGrid::recvAddScalar(CEventServer& event)
1713   {
1714
1715      CBufferIn* buffer = event.subEvents.begin()->buffer;
1716      string id;
1717      *buffer >> id;
1718      get(id)->recvAddScalar(*buffer);
1719   }
1720
1721   /*!
1722   \brief Receive a message annoucing the creation of an scalar on server side
1723   \param[in] buffer Buffer containing message
1724   */
1725   void CGrid::recvAddScalar(CBufferIn& buffer)
1726   {
1727      string id;
1728      buffer >> id;
1729      addScalar(id);
1730   }
1731
1732  /*!
1733  \brief Solve domain and axis references
1734  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1735  all attributes from their parents, they should be processed with this function
1736  \param[in] apply inherit all attributes of parents (true)
1737  */
1738  void CGrid::solveDomainAxisRefInheritance(bool apply)
1739  {
1740    CContext* context = CContext::getCurrent();
1741    unsigned int vecSize, i;
1742    std::vector<StdString>::iterator it, itE;
1743    setDomainList();
1744    it = domList_.begin(); itE = domList_.end();
1745    for (; it != itE; ++it)
1746    {
1747      CDomain* pDom = CDomain::get(*it);
1748      if (context->hasClient)
1749      {
1750        pDom->solveRefInheritance(apply);
1751        pDom->solveInheritanceTransformation();
1752      }
1753    }
1754
1755    setAxisList();
1756    it = axisList_.begin(); itE = axisList_.end();
1757    for (; it != itE; ++it)
1758    {
1759      CAxis* pAxis = CAxis::get(*it);
1760      if (context->hasClient)
1761      {
1762        pAxis->solveRefInheritance(apply);
1763        pAxis->solveInheritanceTransformation();
1764      }
1765    }
1766
1767    setScalarList();
1768    it = scalarList_.begin(); itE = scalarList_.end();
1769    for (; it != itE; ++it)
1770    {
1771      CScalar* pScalar = CScalar::get(*it);
1772      if (context->hasClient)
1773      {
1774        pScalar->solveRefInheritance(apply);
1775        pScalar->solveInheritanceTransformation();
1776      }
1777    }
1778  }
1779
1780  bool CGrid::isTransformed()
1781  {
1782    return isTransformed_;
1783  }
1784
1785  void CGrid::setTransformed()
1786  {
1787    isTransformed_ = true;
1788  }
1789
1790  CGridTransformation* CGrid::getTransformations()
1791  {
1792    return transformations_;
1793  }
1794
1795  void CGrid::addTransGridSource(CGrid* gridSrc)
1796  {
1797    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1798      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1799  }
1800
1801  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1802  {
1803    return gridSrc_;
1804  }
1805
1806  /*!
1807     Complete all the necessary (and lacking) attributes of a grid
1808     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1809  */
1810  void CGrid::completeGrid(CGrid* transformGridSrc)
1811  {
1812    if (0 != transformGridSrc)
1813    {
1814      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1815      {
1816        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1817             << "Two grids have different number of elements. " << std::endl
1818             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1819             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1820      }
1821    }
1822
1823    if (isGenerated()) return;
1824    setGenerated();
1825
1826    CGridGenerate gridGenerate(this, transformGridSrc);
1827    gridGenerate.completeGrid();
1828  }
1829
1830  bool CGrid::isGenerated()
1831  {
1832    return isGenerated_;
1833  }
1834
1835  void CGrid::setGenerated()
1836  {
1837    isGenerated_ = true;
1838  }
1839
1840  void CGrid::transformGrid(CGrid* transformGridSrc)
1841  {
1842    if (!transformGridSrc)
1843      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1844            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1845
1846    if (isTransformed()) return;
1847    setTransformed();
1848    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1849    {
1850      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1851           << "Two grids have different number of elements. " << std::endl
1852           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1853           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1854    }
1855    else
1856    {
1857    }
1858
1859    transformations_ = new CGridTransformation(this, transformGridSrc);
1860    transformations_->computeAll();
1861    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1862
1863    // Ok, now need to compute index of grid source
1864    transformGridSrc->checkMaskIndex(false);
1865  }
1866
1867  bool CGrid::hasTransform()
1868  {
1869    if (hasTransform_) return hasTransform_;
1870
1871    std::vector<CDomain*> domList = getDomains();
1872    std::vector<CAxis*> axisList = getAxis();
1873    std::vector<CScalar*> scalarList = getScalars();
1874
1875    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
1876    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
1877    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
1878
1879    return hasTransform_;
1880  }
1881
1882  /*!
1883  \brief Get the list of domain pointers
1884  \return list of domain pointers
1885  */
1886  std::vector<CDomain*> CGrid::getDomains()
1887  {
1888    std::vector<CDomain*> domList;
1889    if (!domList_.empty())
1890    {
1891      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1892    }
1893    return domList;
1894  }
1895
1896  /*!
1897  \brief Get the list of  axis pointers
1898  \return list of axis pointers
1899  */
1900  std::vector<CAxis*> CGrid::getAxis()
1901  {
1902    std::vector<CAxis*> aList;
1903    if (!axisList_.empty())
1904      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1905
1906    return aList;
1907  }
1908
1909  /*!
1910  \brief Get the list of  axis pointers
1911  \return list of axis pointers
1912  */
1913  std::vector<CScalar*> CGrid::getScalars()
1914  {
1915    std::vector<CScalar*> sList;
1916    if (!scalarList_.empty())
1917      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
1918
1919    return sList;
1920  }
1921
1922  /*!
1923  \brief Get domain pointer with index
1924  \return domain pointer
1925  */
1926  CDomain* CGrid::getDomain(int domainIndex)
1927  {
1928    std::vector<CDomain*> domainListP = this->getDomains();
1929    if (domainListP.empty())
1930    {
1931      ERROR("CGrid::getDomain(int domainIndex)",
1932            << "No domain associated to this grid. " << std::endl
1933            << "Grid id = " << this->getId());
1934    }
1935
1936    if (domainIndex >= domainListP.size() || (domainIndex < 0))
1937      ERROR("CGrid::getDomain(int domainIndex)",
1938            << "Domain with the index doesn't exist " << std::endl
1939            << "Grid id = " << this->getId() << std::endl
1940            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
1941
1942    return domainListP[domainIndex];
1943  }
1944
1945  /*!
1946  \brief Get the axis pointer with index
1947  \return axis pointer
1948  */
1949  CAxis* CGrid::getAxis(int axisIndex)
1950  {
1951    std::vector<CAxis*> axisListP = this->getAxis();
1952    if (axisListP.empty())
1953    {
1954      ERROR("CGrid::getDomain(int axisIndex)",
1955            << "No axis associated to this grid. " << std::endl
1956            << "Grid id = " << this->getId());
1957    }
1958
1959    if (axisIndex >= axisListP.size() || (axisIndex < 0))
1960      ERROR("CGrid::getDomain(int axisIndex)",
1961            << "Domain with the index doesn't exist " << std::endl
1962            << "Grid id = " << this->getId() << std::endl
1963            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
1964
1965    return axisListP[axisIndex];
1966  }
1967
1968  /*!
1969  \brief Get the a scalar pointer
1970  \return scalar pointer
1971  */
1972  CScalar* CGrid::getScalar(int scalarIndex)
1973  {
1974    std::vector<CScalar*> scalarListP = this->getScalars();
1975    if (scalarListP.empty())
1976    {
1977      ERROR("CGrid::getScalar(int scalarIndex)",
1978            << "No scalar associated to this grid. " << std::endl
1979            << "Grid id = " << this->getId());
1980    }
1981
1982    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
1983      ERROR("CGrid::getScalar(int scalarIndex)",
1984            << "Scalar with the index doesn't exist " << std::endl
1985            << "Grid id = " << this->getId() << std::endl
1986            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
1987
1988    return scalarListP[scalarIndex];
1989  }
1990
1991  /*!
1992  \brief Set domain(s) of a grid from a list
1993  \param[in] domains list of domains
1994  */
1995  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1996  {
1997    if (isDomListSet) return;
1998    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1999    if (!domains.empty() && domList.empty())
2000    {
2001      for (int i = 0; i < domains.size(); ++i)
2002        this->getVirtualDomainGroup()->addChild(domains[i]);
2003      domList = this->getVirtualDomainGroup()->getAllChildren();
2004    }
2005
2006    if (!domList.empty())
2007    {
2008      int sizeDom = domList.size();
2009      domList_.resize(sizeDom);
2010      for (int i = 0; i < sizeDom; ++i)
2011      {
2012        domList_[i] = domList[i]->getId();
2013      }
2014      isDomListSet = true;
2015    }
2016
2017  }
2018
2019  /*!
2020  \brief Set axis(s) of a grid from a list
2021  \param[in] axis list of axis
2022  */
2023  void CGrid::setAxisList(const std::vector<CAxis*> axis)
2024  {
2025    if (isAxisListSet) return;
2026    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2027    if (!axis.empty() && aList.empty())
2028    {
2029      for (int i = 0; i < axis.size(); ++i)
2030        this->getVirtualAxisGroup()->addChild(axis[i]);
2031      aList = this->getVirtualAxisGroup()->getAllChildren();
2032    }
2033
2034    if (!aList.empty())
2035    {
2036      int sizeAxis = aList.size();
2037      axisList_.resize(sizeAxis);
2038      for (int i = 0; i < sizeAxis; ++i)
2039      {
2040        axisList_[i] = aList[i]->getId();
2041      }
2042      isAxisListSet = true;
2043    }
2044  }
2045
2046  /*!
2047  \brief Set scalar(s) of a grid from a list
2048  \param[in] scalars list of scalars
2049  */
2050  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
2051  {
2052    if (isScalarListSet) return;
2053    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2054    if (!scalars.empty() && sList.empty())
2055    {
2056      for (int i = 0; i < scalars.size(); ++i)
2057        this->getVirtualScalarGroup()->addChild(scalars[i]);
2058      sList = this->getVirtualScalarGroup()->getAllChildren();
2059    }
2060
2061    if (!sList.empty())
2062    {
2063      int sizeScalar = sList.size();
2064      scalarList_.resize(sizeScalar);
2065      for (int i = 0; i < sizeScalar; ++i)
2066      {
2067        scalarList_[i] = sList[i]->getId();
2068      }
2069      isScalarListSet = true;
2070    }
2071  }
2072
2073  /*!
2074  \brief Get list of id of domains
2075  \return id list of domains
2076  */
2077  std::vector<StdString> CGrid::getDomainList()
2078  {
2079    setDomainList();
2080    return domList_;
2081  }
2082
2083  /*!
2084  \brief Get list of id of axis
2085  \return id list of axis
2086  */
2087  std::vector<StdString> CGrid::getAxisList()
2088  {
2089    setAxisList();
2090    return axisList_;
2091  }
2092
2093  /*!
2094  \brief Get list of id of scalar
2095  \return id list of scalar
2096  */
2097  std::vector<StdString> CGrid::getScalarList()
2098  {
2099    setScalarList();
2100    return scalarList_;
2101  }
2102
2103  /*!
2104    Send all attributes of domains from client to server
2105  */
2106  void CGrid::sendAllDomains()
2107  {
2108    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2109    int dSize = domList.size();
2110    for (int i = 0; i < dSize; ++i)
2111    {
2112      sendAddDomain(domList[i]->getId());
2113      domList[i]->sendAllAttributesToServer();
2114    }
2115  }
2116
2117  /*!
2118    Send all attributes of axis from client to server
2119  */
2120  void CGrid::sendAllAxis()
2121  {
2122    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2123    int aSize = aList.size();
2124
2125    for (int i = 0; i < aSize; ++i)
2126    {
2127      sendAddAxis(aList[i]->getId());
2128      aList[i]->sendAllAttributesToServer();
2129    }
2130  }
2131
2132  /*!
2133    Send all attributes of scalars from client to server
2134  */
2135  void CGrid::sendAllScalars()
2136  {
2137    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2138    int sSize = sList.size();
2139
2140    for (int i = 0; i < sSize; ++i)
2141    {
2142      sendAddScalar(sList[i]->getId());
2143      sList[i]->sendAllAttributesToServer();
2144    }
2145  }
2146
2147  /*!
2148    Parse a grid, for now, it contains only domain, axis and scalar
2149  */
2150  void CGrid::parse(xml::CXMLNode& node)
2151  {
2152    SuperClass::parse(node);
2153
2154    if (node.goToChildElement())
2155    {
2156      StdString domainName("domain");
2157      StdString axisName("axis");
2158      StdString scalarName("scalar");
2159      do
2160      {
2161        if (node.getElementName() == domainName) {
2162          order_.push_back(2);
2163          this->getVirtualDomainGroup()->parseChild(node);
2164        }
2165        if (node.getElementName() == axisName) {
2166          order_.push_back(1);
2167          this->getVirtualAxisGroup()->parseChild(node);
2168        }
2169        if (node.getElementName() == scalarName) {
2170          order_.push_back(0);
2171          this->getVirtualScalarGroup()->parseChild(node);
2172        }
2173      } while (node.goToNextElement());
2174      node.goToParentElement();
2175    }
2176
2177    if (!order_.empty())
2178    {
2179      int sizeOrd = order_.size();
2180      axis_domain_order.resize(sizeOrd);
2181      for (int i = 0; i < sizeOrd; ++i)
2182      {
2183        axis_domain_order(i) = order_[i];
2184      }
2185    }
2186
2187    setDomainList();
2188    setAxisList();
2189    setScalarList();
2190   }
2191} // namespace xios
Note: See TracBrowser for help on using the repository browser.