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

Last change on this file since 764 was 764, checked in by rlacroix, 8 years ago

Fix the buffer size estimation to avoid requests for unexpected buffers.

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