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

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

Add support for indexed output.

If the new field attribute "indexed_output" is set to true and a mask is defined (either at grid, domain or axis level), the indexed data will be outputed instead of the full data with missing values.

See http://cfconventions.org/Data/cf-conventions/cf-conventions-1.5/build/cf-conventions.html#compression-by-gathering for more information.

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