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

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

Adding Fortran interfaces for retrieving domains, axis, scalars of a field

+) Add some functions in Grid to get its domain, axis, scalar

Test
+) On Curie
+) Work

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