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

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

Correctly estimate the needed buffer sizes.

The attributes were not considered which could lead to incorrect estimations.

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