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

Last change on this file since 887 was 887, checked in by mhnguyen, 8 years ago

Adding a new type of element into grid: Scalar

+) Add a new node Scalar for xml
+) Make some change on writing scalar value
+) Reorganize some codes
+) Remove some redundant codes

Test
+) On Curie
+) All tests pass

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