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

Last change on this file since 739 was 739, checked in by rlacroix, 6 years ago

Fix a small mistake in the buffer size evaluation.

The issue affected only the server to client communications.

  • 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: 44.9 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20
21namespace xios {
22
23   /// ////////////////////// Définitions ////////////////////// ///
24
25   CGrid::CGrid(void)
26      : CObjectTemplate<CGrid>(), CGridAttributes()
27      , isChecked(false), isDomainAxisChecked(false)
28      , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false)
29      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
30      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
31      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
32      , transformations_(0), isTransformed_(false)
33      , axisPositionInGrid_(), positionDimensionDistributed_(1)
34   {
35     setVirtualDomainGroup();
36     setVirtualAxisGroup();
37   }
38
39   CGrid::CGrid(const StdString& id)
40      : CObjectTemplate<CGrid>(id), CGridAttributes()
41      , isChecked(false), isDomainAxisChecked(false)
42      , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false)
43      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
44      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
45      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
46      , transformations_(0), isTransformed_(false)
47      , axisPositionInGrid_(), positionDimensionDistributed_(1)
48   {
49     setVirtualDomainGroup();
50     setVirtualAxisGroup();
51   }
52
53   CGrid::~CGrid(void)
54   {
55    if (0 != clientDistribution_) delete clientDistribution_;
56    if (0 != serverDistribution_) delete serverDistribution_;
57    if (0 != clientServerMap_) delete clientServerMap_;
58    if (0 != transformations_) delete transformations_;
59   }
60
61   ///---------------------------------------------------------------
62
63   StdString CGrid::GetName(void)    { return StdString("grid"); }
64   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
65   ENodeType CGrid::GetType(void)    { return eGrid; }
66
67
68   StdSize CGrid::getDimension(void) const
69   {
70      return globalDim_.size();
71   }
72
73   //---------------------------------------------------------------
74
75   StdSize CGrid::getDataSize(void) const
76   {
77     StdSize retvalue = 1;
78     if (!isScalarGrid())
79     {
80       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
81       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];
82     }
83     return retvalue;
84   }
85
86   /*!
87    * Compute the minimum buffer size required to send the attributes to the server(s).
88    *
89    * \return A map associating the server rank with its minimum buffer size.
90    */
91   std::map<int, StdSize> CGrid::getAttributesBufferSize()
92   {
93     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
94
95     // The grid indexes require a similar size as the actual data
96     std::map<int, StdSize> dataSizes = getDataBufferSize();
97     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
98     for (it = dataSizes.begin(); it != itE; ++it)
99     {
100       it->second += 2 * sizeof(bool);
101       if (it->second > attributesSizes[it->first])
102         attributesSizes[it->first] = it->second;
103     }
104
105     // Account for the axis attributes
106     std::vector<CAxis*> axisList = getAxis();
107     for (size_t i = 0; i < axisList.size(); ++i)
108     {
109       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize();
110       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
111       {
112         if (it->second > attributesSizes[it->first])
113           attributesSizes[it->first] = it->second;
114       }
115     }
116
117     // Account for the domain attributes
118     std::vector<CDomain*> domList = getDomains();
119     for (size_t i = 0; i < domList.size(); ++i)
120     {
121       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize();
122       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
123       {
124         if (it->second > attributesSizes[it->first])
125           attributesSizes[it->first] = it->second;
126       }
127     }
128     
129     return attributesSizes;
130   }
131
132   /*!
133    * Compute the minimum buffer size required to send the data to the server(s).
134    *
135    * \param id the id used to tag the data
136    * \return A map associating the server rank with its minimum buffer size.
137    */
138   std::map<int, StdSize> CGrid::getDataBufferSize(const std::string& id /*= ""*/)
139   {
140     std::map<int, StdSize> dataSizes;
141     // The record index is sometimes sent along with the data but we always
142     // include it in the size calculation for the sake of simplicity
143     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() + 2 * sizeof(size_t);
144
145     std::map<int, size_t>::const_iterator itb = connectedDataSize_.begin(), it, itE = connectedDataSize_.end();
146     for (it = itb; it != itE; ++it)
147       dataSizes.insert(std::make_pair(it->first, extraSize + CArray<double,1>::size(it->second)));
148
149     return dataSizes;
150   }
151
152   void CGrid::checkAttributesAfterTransformation()
153   {
154     setDomainList();
155     std::vector<CDomain*> domListP = this->getDomains();
156     if (!domListP.empty())
157     {
158       for (int i = 0; i < domListP.size(); ++i)
159       {
160         domListP[i]->checkAttributesOnClientAfterTransformation();
161       }
162     }
163   }
164
165   //---------------------------------------------------------------
166
167   /*!
168    * Test whether the data defined on the grid can be outputted in a compressed way.
169    *
170    * \return true if and only if a mask was defined for this grid
171    */
172   bool CGrid::isCompressible(void) const
173   {
174      return isCompressible_;
175   }
176
177   //---------------------------------------------------------------
178
179   void CGrid::addRelFileCompressed(const StdString& filename)
180   {
181      this->relFilesCompressed.insert(filename);
182   }
183
184   bool CGrid::isWrittenCompressed(const StdString& filename) const
185   {
186      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
187   }
188
189   //---------------------------------------------------------------
190
191   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
192   {
193     if (this->isDomainAxisChecked) return;
194
195     this->solveAxisRef(areAttributesChecked);
196     this->solveDomainRef(areAttributesChecked);
197     computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
198     this->isDomainAxisChecked = areAttributesChecked;
199   }
200
201   void CGrid::checkEligibilityForCompressedOutput()
202   {
203     // We don't check if the mask is valid here, just if a mask has been defined at this point.
204     isCompressible_ = !mask1.isEmpty() || !mask2.isEmpty() || !mask3.isEmpty();
205   }
206
207   void CGrid::checkMaskIndex(bool doSendingIndex)
208   {
209     CContext* context = CContext::getCurrent();
210     CContextClient* client=context->client;
211
212     if (isScalarGrid())
213     {
214       if (context->hasClient)
215          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
216
217       if (this->isChecked) return;
218       if (context->hasClient)
219       {
220          this->computeIndexScalarGrid();
221       }
222
223       this->isChecked = true;
224       return;
225     }
226
227     if (context->hasClient)
228      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
229
230     if (this->isChecked) return;
231
232     if (context->hasClient)
233     {
234        this->checkAttributesAfterTransformation();
235        this->checkMask();
236        this->computeIndex();
237     }
238     this->isChecked = true;
239   }
240
241   void CGrid::checkMask(void)
242   {
243      using namespace std;
244      std::vector<CDomain*> domainP = this->getDomains();
245      std::vector<CAxis*> axisP = this->getAxis();
246      int dim = domainP.size() * 2 + axisP.size();
247
248      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
249      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
250      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
251      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
252
253      switch (dim) {
254        case 1:
255          checkGridMask(mask1, domainMasks, axisMasks, axis_domain_order);
256          break;
257        case 2:
258          checkGridMask(mask2, domainMasks, axisMasks, axis_domain_order);
259          break;
260        case 3:
261          checkGridMask(mask3, domainMasks, axisMasks, axis_domain_order);
262          break;
263//        case 4:
264//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
265//          break;
266//        case 5:
267//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
268//          break;
269//        case 6:
270//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
271//          break;
272//        case 7:
273//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
274//          break;
275        default:
276          break;
277      }
278   }
279
280   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
281   {
282      using namespace std;
283      std::vector<CDomain*> domainP = this->getDomains();
284      std::vector<CAxis*> axisP = this->getAxis();
285      int dim = domainP.size() * 2 + axisP.size();
286
287      switch (dim) {
288        case 1:
289          modifyGridMask(mask1, indexToModify);
290          break;
291        case 2:
292          modifyGridMask(mask2, indexToModify);
293          break;
294        case 3:
295          modifyGridMask(mask3, indexToModify);
296          break;
297
298        default:
299          break;
300      }
301   }
302
303   //---------------------------------------------------------------
304
305   void CGrid::solveDomainRef(bool sendAtt)
306   {
307      setDomainList();
308      std::vector<CDomain*> domListP = this->getDomains();
309      if (!domListP.empty())
310      {
311        for (int i = 0; i < domListP.size(); ++i)
312        {
313          if (sendAtt) domListP[i]->sendCheckedAttributes();
314          else domListP[i]->checkAttributesOnClient();
315        }
316      }
317   }
318
319   //---------------------------------------------------------------
320
321   void CGrid::solveAxisRef(bool sendAtt)
322   {
323      setAxisList();
324      std::vector<CAxis*> axisListP = this->getAxis();
325      if (!axisListP.empty())
326      {
327        int idx = 0;
328        axisPositionInGrid_.resize(0);
329        for (int i = 0; i < axis_domain_order.numElements(); ++i)
330        {
331          if (false == axis_domain_order(i))
332          {
333            axisPositionInGrid_.push_back(idx);
334            ++idx;
335          }
336          else idx += 2;
337        }
338
339        for (int i = 0; i < axisListP.size(); ++i)
340        {
341          if (sendAtt)
342            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
343          else
344            axisListP[i]->checkAttributesOnClient(globalDim_,axisPositionInGrid_[i]);
345          ++idx;
346        }
347      }
348   }
349
350   std::vector<int> CGrid::getAxisPositionInGrid() const
351   {
352     return axisPositionInGrid_;
353   }
354
355   //---------------------------------------------------------------
356
357   void CGrid::computeIndex(void)
358   {
359     CContext* context = CContext::getCurrent();
360     CContextClient* client = context->client;
361
362     // First of all, compute distribution on client side
363     clientDistribution_ = new CDistributionClient(client->clientRank, this);
364     // Get local data index on client
365     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
366     int nbStoreIndex = storeIndex_client.numElements();
367     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
368     isDataDistributed_= clientDistribution_->isDataDistributed();
369
370     if (!doGridHaveDataDistributed())
371     {
372        if (0 == client->clientRank)
373        {
374          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
375          for (int rank = 0; rank < client->serverSize; ++rank)
376            connectedDataSize_[rank] = ssize;
377        }
378        return;
379     }
380
381     // Compute mapping between client and server
382     size_t globalSizeIndex = 1, indexBegin, indexEnd;
383     int range, clientSize = client->clientSize;
384     for (int i = 0; i < globalDim_.size(); ++i) globalSizeIndex *= globalDim_[i];
385     indexBegin = 0;
386     for (int i = 0; i < clientSize; ++i)
387     {
388       range = globalSizeIndex / clientSize;
389       if (i < (globalSizeIndex%clientSize)) ++range;
390       if (i == client->clientRank) break;
391       indexBegin += range;
392     }
393     indexEnd = indexBegin + range - 1;
394
395     // Then compute distribution on server side
396     CServerDistributionDescription serverDistributionDescription(globalDim_);
397     serverDistributionDescription.computeServerGlobalIndexInRange(client->serverSize,
398                                                                   std::make_pair<size_t,size_t>(indexBegin, indexEnd),
399                                                                   positionDimensionDistributed_);
400
401     // Finally, compute index mapping between client(s) and server(s)
402     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription.getGlobalIndexRange(),
403                                                            client->intraComm,
404                                                            clientDistribution_->isDataDistributed());
405
406     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex());
407     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
408
409     const std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
410     std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
411     itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
412     iteGlobalMap = globalIndexOnServer.end();
413
414     typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
415     std::vector<int>::iterator itVec;
416     int nbGlobalIndex = globalIndexSendToServer.size();
417     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
418     {
419       int serverRank = itGlobalMap->first;
420       int indexSize = itGlobalMap->second.size();
421       std::vector<int> permutIndex(indexSize);
422       XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
423       XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
424       BinarySearch binSearch(itGlobalMap->second);
425       for (int i = 0; i < nbGlobalIndex; ++i)
426       {
427         if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexSendToServer[i], itVec))
428         {
429           if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
430             connectedDataSize_[serverRank] = 1;
431           else
432             ++connectedDataSize_[serverRank];
433         }
434       }
435     }
436
437     connectedServerRank_.clear();
438     for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
439       connectedServerRank_.push_back(it->first);
440     }
441     if (!connectedDataSize_.empty())
442     {
443       connectedServerRank_.clear();
444       for (std::map<int,size_t>::const_iterator it = connectedDataSize_.begin(); it != connectedDataSize_.end(); ++it)
445         connectedServerRank_.push_back(it->first);
446     }
447
448     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
449   }
450
451   //----------------------------------------------------------------
452
453   CGrid* CGrid::createGrid(CDomain* domain)
454   {
455      std::vector<CDomain*> vecDom(1,domain);
456      std::vector<CAxis*> vecAxis;
457      CArray<bool,1> axisDomainOrder;
458      CGrid* grid = createGrid(vecDom, vecAxis, axisDomainOrder);
459
460      return grid;
461   }
462
463   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
464   {
465      std::vector<CDomain*> vecDom(1,domain);
466      std::vector<CAxis*> vecAxis(1,axis);
467      CArray<bool,1> axisDomainOrder;
468      CGrid* grid = createGrid(vecDom, vecAxis, axisDomainOrder);
469
470      return grid;
471   }
472
473   CGrid* CGrid::createGrid(std::vector<CDomain*> domains, std::vector<CAxis*> axis, CArray<bool,1> axisDomainOrder)
474   {
475      StdString new_id = StdString("__");
476      if (!domains.empty()) for (int i = 0; i < domains.size(); ++i) new_id += domains[i]->getId() + StdString("_");
477      if (!axis.empty()) for (int i = 0; i < axis.size(); ++i) new_id += axis[i]->getId() + StdString("_");
478      if (domains.empty() && axis.empty()) new_id += StdString("scalar_grid");
479      new_id += StdString("_");
480
481      CGrid* grid = CGridGroup::get("grid_definition")->createChild(new_id);
482      grid->setDomainList(domains);
483      grid->setAxisList(axis);
484
485      //By default, domains are always the first ones of a grid
486      if (0 == axisDomainOrder.numElements())
487      {
488        int size = domains.size()+axis.size();
489        grid->axis_domain_order.resize(size);
490        for (int i = 0; i < size; ++i)
491        {
492          if (i < domains.size()) grid->axis_domain_order(i) = true;
493          else grid->axis_domain_order(i) = false;
494        }
495      }
496      else
497      {
498        grid->axis_domain_order.resize(axisDomainOrder.numElements());
499        grid->axis_domain_order = axisDomainOrder;
500      }
501
502      grid->computeGridGlobalDimension(domains, axis, grid->axis_domain_order);
503
504      return grid;
505   }
506
507   CDomainGroup* CGrid::getVirtualDomainGroup() const
508   {
509     return this->vDomainGroup_;
510   }
511
512   CAxisGroup* CGrid::getVirtualAxisGroup() const
513   {
514     return this->vAxisGroup_;
515   }
516
517   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
518   {
519     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
520     StdSize numElements = stored.numElements();
521     for (StdSize n = 0; n < numElements; ++n)
522     {
523       field[out_i(n)] = stored(n);
524     }
525   }
526
527   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
528   {
529     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
530     StdSize numElements = stored.numElements();
531     for (StdSize n = 0; n < numElements; ++n)
532     {
533       stored(n) = field[out_i(n)];
534     }
535   }
536
537   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
538   {
539     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
540     StdSize numElements = stored.numElements();
541     for (StdSize n = 0; n < numElements; ++n)
542     {
543       field[out_i(n)] = stored(n);
544     }
545   }
546
547   //----------------------------------------------------------------
548
549   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
550   {
551      const StdSize size = storeIndex_client.numElements();
552
553      stored.resize(size);
554      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
555   }
556
557   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
558   {
559      const StdSize size = storeIndex_client.numElements();
560
561      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
562   }
563
564  void CGrid::computeIndexScalarGrid()
565  {
566    CContext* context = CContext::getCurrent();
567    CContextClient* client=context->client;
568
569    storeIndex_client.resize(1);
570    storeIndex_client[0] = 0;
571    if (0 == client->clientRank)
572    {
573      for (int rank = 0; rank < client->serverSize; ++rank)
574        connectedDataSize_[rank] = 1;
575    }
576    isDataDistributed_ = false;
577  }
578
579  void CGrid::computeCompressedIndex()
580  {
581    compressedOutIndexFromClient = outIndexFromClient;
582
583    std::map<size_t, size_t> indexes;
584
585    {
586      std::map<int, CArray<size_t,1> >::const_iterator it = compressedOutIndexFromClient.begin();
587      std::map<int, CArray<size_t,1> >::const_iterator itEnd = compressedOutIndexFromClient.end();
588      for (; it != itEnd; ++it)
589      {
590        for (int i = 0; i < it->second.numElements(); ++i)
591          indexes.insert(std::make_pair(it->second(i), 0));
592      }
593    }
594
595    {
596      std::map<size_t, size_t>::iterator it = indexes.begin();
597      std::map<size_t, size_t>::iterator itEnd = indexes.end();
598      for (size_t i = 0; it != itEnd; ++it, ++i)
599        it->second = i;
600    }
601
602    {
603      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
604      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
605      for (; it != itEnd; ++it)
606      {
607        for (int i = 0; i < it->second.numElements(); ++i)
608          it->second(i) = indexes[it->second(i)];
609      }
610    }
611  }
612
613  void CGrid::sendIndexScalarGrid()
614  {
615    CContext* context = CContext::getCurrent();
616    CContextClient* client = context->client;
617
618    CEventClient event(getType(), EVENT_ID_INDEX);
619    list<CMessage> listMsg;
620    list<CArray<size_t,1> > listOutIndex;
621
622    if (0 == client->clientRank)
623    {
624      for (int rank = 0; rank < client->serverSize; ++rank)
625      {
626        int nb = 1;
627        storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(nb)));
628        listOutIndex.push_back(CArray<size_t,1>(nb));
629
630        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
631        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
632
633        for (int k = 0; k < nb; ++k)
634        {
635          outGlobalIndexOnServer(k) = 0;
636          outLocalIndexToServer(k)  = 0;
637        }
638
639        listMsg.push_back(CMessage());
640        listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
641
642        event.push(rank, 1, listMsg.back());
643      }
644
645      client->sendEvent(event);
646    }
647    else
648      client->sendEvent(event);
649  }
650
651  void CGrid::sendIndex(void)
652  {
653    CContext* context = CContext::getCurrent();
654    CContextClient* client = context->client;
655
656    CEventClient event(getType(), EVENT_ID_INDEX);
657    int rank;
658    list<CMessage> listMsg;
659    list<CArray<size_t,1> > listOutIndex;
660    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
661    const std::vector<int>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
662    const std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
663
664    if (!doGridHaveDataDistributed())
665    {
666      if (0 == client->clientRank)
667      {
668        CArray<size_t,1> outGlobalIndexOnServer(globalIndexSendToServer.size());
669        for (int idx = 0; idx < globalIndexSendToServer.size();++idx)
670          outGlobalIndexOnServer(idx) = globalIndexSendToServer[idx];
671
672        CArray<int,1> outLocalIndexToServer(localIndexSendToServer.size());
673        for (int idx = 0; idx < localIndexSendToServer.size();++idx)
674          outLocalIndexToServer(idx) = localIndexSendToServer[idx];
675
676        for (rank = 0; rank < client->serverSize; ++rank)
677        {
678          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
679          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
680
681          listMsg.push_back(CMessage());
682          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
683
684          event.push(rank, 1, listMsg.back());
685        }
686
687        client->sendEvent(event);
688      }
689      else
690        client->sendEvent(event);
691    }
692    else
693    {
694      std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
695      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
696      iteGlobalMap = globalIndexOnServer.end();
697
698      int nbGlobalIndex = globalIndexSendToServer.size();
699      std::map<int,std::vector<int> >localIndexTmp;
700      std::map<int,std::vector<size_t> > globalIndexTmp;
701
702      typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
703      std::vector<int>::iterator itVec;
704      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
705      {
706        int serverRank = itGlobalMap->first;
707        int indexSize = itGlobalMap->second.size();
708        std::vector<int> permutIndex(indexSize);
709        XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
710        XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
711        BinarySearch binSearch(itGlobalMap->second);
712
713        for (int i = 0; i < nbGlobalIndex; ++i)
714        {
715          if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexSendToServer[i], itVec))
716          {
717            globalIndexTmp[serverRank].push_back(globalIndexSendToServer[i]);
718            localIndexTmp[serverRank].push_back(localIndexSendToServer[i]);
719          }
720        }
721      }
722
723      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
724      {
725        rank = connectedServerRank_[ns];
726        int nb = 0;
727        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
728          nb = globalIndexTmp[rank].size();
729
730        storeIndex_toSrv.insert(make_pair(rank, CArray<int,1>(nb)));
731        listOutIndex.push_back(CArray<size_t,1>(nb));
732
733        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
734        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
735
736        for (int k = 0; k < nb; ++k)
737        {
738          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
739          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
740        }
741
742        listMsg.push_back(CMessage());
743        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
744
745        event.push(rank, nbSenders[rank], listMsg.back());
746      }
747
748      client->sendEvent(event);
749    }
750  }
751
752  void CGrid::recvIndex(CEventServer& event)
753  {
754    string gridId;
755    vector<int> ranks;
756    vector<CBufferIn*> buffers;
757
758    list<CEventServer::SSubEvent>::iterator it;
759    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
760    {
761      ranks.push_back(it->rank);
762      CBufferIn* buffer = it->buffer;
763      *buffer >> gridId;
764      buffers.push_back(buffer);
765    }
766    get(gridId)->recvIndex(ranks, buffers);
767  }
768
769  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
770                                         const std::vector<CAxis*>& axis,
771                                         const CArray<bool,1>& axisDomainOrder)
772  {
773    globalDim_.resize(domains.size()*2+axis.size());
774    int idx = 0, idxDomain = 0, idxAxis = 0;
775    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
776    {
777      if (axisDomainOrder(i))
778      {
779        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
780        {
781          positionDimensionDistributed_ = idx;
782        }
783        else
784        {
785          positionDimensionDistributed_ = idx +1;
786        }
787
788        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
789        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
790
791        ++idxDomain;
792        idx += 2;
793      }
794      else
795      {
796        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
797        ++idxAxis;
798        ++idx;
799      }
800    }
801  }
802
803  std::vector<int> CGrid::getGlobalDimension()
804  {
805    return globalDim_;
806  }
807
808  bool CGrid::isScalarGrid() const
809  {
810    return (axisList_.empty() && domList_.empty());
811  }
812
813  /*!
814    Verify whether one server need to write data
815    There are some cases on which one server has nodata to write. For example, when we
816    just only want to zoom on a domain.
817  */
818  bool CGrid::doGridHaveDataToWrite()
819  {
820     return (0 != writtenDataSize_);
821  }
822
823  /*!
824    Return size of data which is written on each server
825    Whatever dimension of a grid, data which are written on server must be presented as
826    an one dimension array.
827    \return size of data written on server
828  */
829  size_t CGrid::getWrittenDataSize() const
830  {
831    return writtenDataSize_;
832  }
833
834  /*!
835    Returns the number of indexes written by each server.
836    \return the number of indexes written by each server
837  */
838  int CGrid::getNumberWrittenIndexes() const
839  {
840    return numberWrittenIndexes_;
841  }
842
843  /*!
844    Returns the total number of indexes written by the servers.
845    \return the total number of indexes written by the servers
846  */
847  int CGrid::getTotalNumberWrittenIndexes() const
848  {
849    return totalNumberWrittenIndexes_;
850  }
851
852  /*!
853    Returns the offset of indexes written by each server.
854    \return the offset of indexes written by each server
855  */
856  int CGrid::getOffsetWrittenIndexes() const
857  {
858    return offsetWrittenIndexes_;
859  }
860
861  const CDistributionServer* CGrid::getDistributionServer() const
862  {
863    return serverDistribution_;
864  }
865
866  const CDistributionClient* CGrid::getDistributionClient() const
867  {
868    return clientDistribution_;
869  }
870
871  bool CGrid::doGridHaveDataDistributed()
872  {
873    if (isScalarGrid()) return false;
874    else
875      return isDataDistributed_;
876  }
877
878  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
879  {
880    CContext* context = CContext::getCurrent();
881    CContextServer* server = context->server;
882    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
883
884    for (int n = 0; n < ranks.size(); n++)
885    {
886      int rank = ranks[n];
887      CBufferIn& buffer = *buffers[n];
888
889      buffer >> isDataDistributed_ >> isCompressible_;
890      size_t dataSize = 0;
891
892      if (isScalarGrid())
893      {
894        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
895        CArray<size_t,1> outIndex;
896        buffer >> outIndex;
897        outIndexFromClient.insert(std::make_pair(rank, outIndex));
898        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
899        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
900                                                      nZoomBeginGlobal, nGlob);
901        return;
902      }
903
904      if (0 == serverDistribution_)
905      {
906        int idx = 0, numElement = axis_domain_order.numElements();
907        int ssize = numElement;
908        std::vector<int> indexMap(numElement);
909        for (int i = 0; i < numElement; ++i)
910        {
911          indexMap[i] = idx;
912          if (true == axis_domain_order(i))
913          {
914            ++ssize;
915            idx += 2;
916          }
917          else
918            ++idx;
919        }
920
921        int axisId = 0, domainId = 0;
922        std::vector<CDomain*> domainList = getDomains();
923        std::vector<CAxis*> axisList = getAxis();
924        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
925        for (int i = 0; i < numElement; ++i)
926        {
927          if (axis_domain_order(i))
928          {
929            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
930            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
931            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
932            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
933
934            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
935            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
936            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
937            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
938            ++domainId;
939          }
940          else
941          {
942            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
943            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
944            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
945            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
946            ++axisId;
947          }
948        }
949        dataSize = 1;
950        for (int i = 0; i < nZoomSize.size(); ++i)
951          dataSize *= nZoomSize[i];
952
953        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
954                                                      nZoomBeginGlobal, nGlob);
955      }
956
957      CArray<size_t,1> outIndex;
958      buffer >> outIndex;
959      if (isDataDistributed_)
960        serverDistribution_->computeLocalIndex(outIndex);
961      else
962      {
963        dataSize = outIndex.numElements();
964        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
965      }
966      writtenDataSize_ += dataSize;
967
968      outIndexFromClient.insert(std::make_pair(rank, outIndex));
969      connectedDataSize_[rank] = outIndex.numElements();
970      numberWrittenIndexes_ += outIndex.numElements();
971    }
972
973    if (isDataDistributed_)
974    {
975      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
976      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
977      offsetWrittenIndexes_ -= numberWrittenIndexes_;
978    }
979    else
980      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
981
982    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
983  }
984
985   /*!
986   \brief Dispatch event received from client
987      Whenever a message is received in buffer of server, it will be processed depending on
988   its event type. A new event type should be added in the switch list to make sure
989   it processed on server side.
990   \param [in] event: Received message
991   */
992  bool CGrid::dispatchEvent(CEventServer& event)
993  {
994
995    if (SuperClass::dispatchEvent(event)) return true;
996    else
997    {
998      switch(event.type)
999      {
1000        case EVENT_ID_INDEX :
1001          recvIndex(event);
1002          return true;
1003          break;
1004
1005         case EVENT_ID_ADD_DOMAIN :
1006           recvAddDomain(event);
1007           return true;
1008           break;
1009
1010         case EVENT_ID_ADD_AXIS :
1011           recvAddAxis(event);
1012           return true;
1013           break;
1014        default :
1015          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1016                << "Unknown Event");
1017          return false;
1018      }
1019    }
1020  }
1021
1022   ///---------------------------------------------------------------
1023
1024   CDomain* CGrid::addDomain(const std::string& id)
1025   {
1026     return vDomainGroup_->createChild(id);
1027   }
1028
1029   CAxis* CGrid::addAxis(const std::string& id)
1030   {
1031     return vAxisGroup_->createChild(id);
1032   }
1033
1034   //! Change virtual field group to a new one
1035   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1036   {
1037      this->vDomainGroup_ = newVDomainGroup;
1038   }
1039
1040   //! Change virtual variable group to new one
1041   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1042   {
1043      this->vAxisGroup_ = newVAxisGroup;
1044   }
1045
1046   //----------------------------------------------------------------
1047   //! Create virtual field group, which is done normally on initializing file
1048   void CGrid::setVirtualDomainGroup(void)
1049   {
1050      this->setVirtualDomainGroup(CDomainGroup::create());
1051   }
1052
1053   //! Create virtual variable group, which is done normally on initializing file
1054   void CGrid::setVirtualAxisGroup(void)
1055   {
1056      this->setVirtualAxisGroup(CAxisGroup::create());
1057   }
1058
1059   /*!
1060   \brief Send a message to create a domain on server side
1061   \param[in] id String identity of domain that will be created on server
1062   */
1063   void CGrid::sendAddDomain(const string& id)
1064   {
1065    CContext* context=CContext::getCurrent();
1066
1067    if (! context->hasServer )
1068    {
1069       CContextClient* client=context->client;
1070
1071       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1072       if (client->isServerLeader())
1073       {
1074         CMessage msg;
1075         msg<<this->getId();
1076         msg<<id;
1077         const std::list<int>& ranks = client->getRanksServerLeader();
1078         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1079           event.push(*itRank,1,msg);
1080         client->sendEvent(event);
1081       }
1082       else client->sendEvent(event);
1083    }
1084   }
1085
1086   /*!
1087   \brief Send a message to create an axis on server side
1088   \param[in] id String identity of axis that will be created on server
1089   */
1090   void CGrid::sendAddAxis(const string& id)
1091   {
1092    CContext* context=CContext::getCurrent();
1093
1094    if (! context->hasServer )
1095    {
1096       CContextClient* client=context->client;
1097
1098       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1099       if (client->isServerLeader())
1100       {
1101         CMessage msg;
1102         msg<<this->getId();
1103         msg<<id;
1104         const std::list<int>& ranks = client->getRanksServerLeader();
1105         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1106           event.push(*itRank,1,msg);
1107         client->sendEvent(event);
1108       }
1109       else client->sendEvent(event);
1110    }
1111   }
1112
1113   /*!
1114   \brief Receive a message annoucing the creation of a domain on server side
1115   \param[in] event Received event
1116   */
1117   void CGrid::recvAddDomain(CEventServer& event)
1118   {
1119
1120      CBufferIn* buffer = event.subEvents.begin()->buffer;
1121      string id;
1122      *buffer >> id;
1123      get(id)->recvAddDomain(*buffer);
1124   }
1125
1126   /*!
1127   \brief Receive a message annoucing the creation of a domain on server side
1128   \param[in] buffer Buffer containing message
1129   */
1130   void CGrid::recvAddDomain(CBufferIn& buffer)
1131   {
1132      string id;
1133      buffer >> id;
1134      addDomain(id);
1135   }
1136
1137   /*!
1138   \brief Receive a message annoucing the creation of an axis on server side
1139   \param[in] event Received event
1140   */
1141   void CGrid::recvAddAxis(CEventServer& event)
1142   {
1143
1144      CBufferIn* buffer = event.subEvents.begin()->buffer;
1145      string id;
1146      *buffer >> id;
1147      get(id)->recvAddAxis(*buffer);
1148   }
1149
1150   /*!
1151   \brief Receive a message annoucing the creation of an axis on server side
1152   \param[in] buffer Buffer containing message
1153   */
1154   void CGrid::recvAddAxis(CBufferIn& buffer)
1155   {
1156      string id;
1157      buffer >> id;
1158      addAxis(id);
1159   }
1160
1161  /*!
1162  \brief Solve domain and axis references
1163  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1164  all attributes from their parents, they should be processed with this function
1165  \param[in] apply inherit all attributes of parents (true)
1166  */
1167  void CGrid::solveDomainAxisRefInheritance(bool apply)
1168  {
1169    CContext* context = CContext::getCurrent();
1170    unsigned int vecSize, i;
1171    std::vector<StdString>::iterator it, itE;
1172    setDomainList();
1173    it = domList_.begin(); itE = domList_.end();
1174    for (; it != itE; ++it)
1175    {
1176      CDomain* pDom = CDomain::get(*it);
1177      if (context->hasClient)
1178      {
1179        pDom->solveRefInheritance(apply);
1180        pDom->solveBaseReference();
1181        pDom->solveSrcInheritance();
1182        pDom->solveInheritanceTransformation();
1183        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1184          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1185      }
1186    }
1187
1188    setAxisList();
1189    it = axisList_.begin(); itE = axisList_.end();
1190    for (; it != itE; ++it)
1191    {
1192      CAxis* pAxis = CAxis::get(*it);
1193      if (context->hasClient)
1194      {
1195        pAxis->solveRefInheritance(apply);
1196        pAxis->solveBaseReference();
1197        pAxis->solveInheritanceTransformation();
1198        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1199          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1200      }
1201    }
1202  }
1203
1204  bool CGrid::isTransformed()
1205  {
1206    return isTransformed_;
1207  }
1208
1209  void CGrid::setTransformed()
1210  {
1211    isTransformed_ = true;
1212  }
1213
1214  CGridTransformation* CGrid::getTransformations()
1215  {
1216    return transformations_;
1217  }
1218
1219  /*!
1220     Complete all the necessary (and lacking) attributes of a grid
1221     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1222  */
1223  void CGrid::completeGrid(CGrid* transformGridSrc)
1224  {
1225    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1226    {
1227      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1228           << "Two grids have different dimension size"
1229           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1230           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1231    }
1232    else
1233    {
1234      int ssize = axis_domain_order.numElements();
1235      for (int i = 0; i < ssize; ++i)
1236        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1237          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1238                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1239                << " don't have elements in the same order");
1240    }
1241
1242    CGridGenerate gridGenerate(this, transformGridSrc);
1243    gridGenerate.completeGrid();
1244  }
1245
1246  void CGrid::transformGrid(CGrid* transformGridSrc)
1247  {
1248    if (isTransformed()) return;
1249    setTransformed();
1250    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1251    {
1252      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1253           << "Two grids have different dimension size"
1254           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1255           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1256    }
1257    else
1258    {
1259      int ssize = axis_domain_order.numElements();
1260      for (int i = 0; i < ssize; ++i)
1261        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1262          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1263                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1264                << " don't have elements in the same order");
1265    }
1266
1267    transformations_ = new CGridTransformation(this, transformGridSrc);
1268    transformations_->computeAll();
1269
1270    // Ok, now need to compute index of grid source
1271    transformGridSrc->checkMaskIndex(false);
1272  }
1273
1274  /*!
1275  \brief Get the list of domain pointers
1276  \return list of domain pointers
1277  */
1278  std::vector<CDomain*> CGrid::getDomains()
1279  {
1280    std::vector<CDomain*> domList;
1281    if (!domList_.empty())
1282    {
1283      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1284    }
1285    return domList;
1286  }
1287
1288  /*!
1289  \brief Get the list of  axis pointers
1290  \return list of axis pointers
1291  */
1292  std::vector<CAxis*> CGrid::getAxis()
1293  {
1294    std::vector<CAxis*> aList;
1295    if (!axisList_.empty())
1296      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1297
1298    return aList;
1299  }
1300
1301  /*!
1302  \brief Set domain(s) of a grid from a list
1303  \param[in] domains list of domains
1304  */
1305  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1306  {
1307    if (isDomListSet) return;
1308    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1309    if (!domains.empty() && domList.empty()) domList = domains;
1310    if (!domList.empty())
1311    {
1312      int sizeDom = domList.size();
1313      domList_.resize(sizeDom);
1314      for (int i = 0; i < sizeDom; ++i)
1315      {
1316        domList_[i] = domList[i]->getId();
1317      }
1318      isDomListSet = true;
1319    }
1320
1321  }
1322
1323  /*!
1324  \brief Set axis(s) of a grid from a list
1325  \param[in] axis list of axis
1326  */
1327  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1328  {
1329    if (isAxisListSet) return;
1330    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1331    if (!axis.empty() && aList.empty()) aList = axis;
1332    if (!aList.empty())
1333    {
1334      int sizeAxis = aList.size();
1335      axisList_.resize(sizeAxis);
1336      for (int i = 0; i < sizeAxis; ++i)
1337      {
1338        axisList_[i] = aList[i]->getId();
1339      }
1340      isAxisListSet = true;
1341    }
1342  }
1343
1344  /*!
1345  \brief Get list of id of domains
1346  \return id list of domains
1347  */
1348  std::vector<StdString> CGrid::getDomainList()
1349  {
1350    setDomainList();
1351    return domList_;
1352  }
1353
1354  /*!
1355  \brief Get list of id of axis
1356  \return id list of axis
1357  */
1358  std::vector<StdString> CGrid::getAxisList()
1359  {
1360    setAxisList();
1361    return axisList_;
1362  }
1363
1364  void CGrid::sendAllDomains()
1365  {
1366    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1367    int dSize = domList.size();
1368    for (int i = 0; i < dSize; ++i)
1369    {
1370      sendAddDomain(domList[i]->getId());
1371      domList[i]->sendAllAttributesToServer();
1372    }
1373  }
1374
1375  void CGrid::sendAllAxis()
1376  {
1377    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1378    int aSize = aList.size();
1379
1380    for (int i = 0; i < aSize; ++i)
1381    {
1382      sendAddAxis(aList[i]->getId());
1383      aList[i]->sendAllAttributesToServer();
1384    }
1385  }
1386
1387  void CGrid::parse(xml::CXMLNode& node)
1388  {
1389    SuperClass::parse(node);
1390
1391    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1392    std::vector<bool> order;
1393
1394    if (node.goToChildElement())
1395    {
1396      StdString domainName("domain");
1397      StdString axisName("axis");
1398      do
1399      {
1400        if (node.getElementName() == domainName) {
1401          order.push_back(true);
1402          this->getVirtualDomainGroup()->parseChild(node);
1403        }
1404        if (node.getElementName() == axisName) {
1405          order.push_back(false);
1406          this->getVirtualAxisGroup()->parseChild(node);
1407        }
1408      } while (node.goToNextElement());
1409      node.goToParentElement();
1410    }
1411
1412    if (!order.empty())
1413    {
1414      int sizeOrd = order.size();
1415      axis_domain_order.resize(sizeOrd);
1416      for (int i = 0; i < sizeOrd; ++i)
1417      {
1418        axis_domain_order(i) = order[i];
1419      }
1420    }
1421
1422    setDomainList();
1423    setAxisList();
1424   }
1425} // namespace xios
Note: See TracBrowser for help on using the repository browser.