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

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

Fix the inherited name for axis/domains with reference in some cases.

Correctly account for transformations and non default ids.

  • 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 itb = connectedDataSize_.begin(), it, itE = connectedDataSize_.end();
146     for (it = itb; it != itE; ++it)
147       dataSizes.insert(std::make_pair(it->first, extraSize + CArray<double,1>::size(it->second)));
148
149     return dataSizes;
150   }
151
152   void CGrid::checkAttributesAfterTransformation()
153   {
154     setDomainList();
155     std::vector<CDomain*> domListP = this->getDomains();
156     if (!domListP.empty())
157     {
158       for (int i = 0; i < domListP.size(); ++i)
159       {
160         domListP[i]->checkAttributesOnClientAfterTransformation();
161       }
162     }
163   }
164
165   //---------------------------------------------------------------
166
167   /*!
168    * Test whether the data defined on the grid can be outputted in a compressed way.
169    *
170    * \return true if and only if a mask was defined for this grid
171    */
172   bool CGrid::isCompressible(void) const
173   {
174      return isCompressible_;
175   }
176
177   //---------------------------------------------------------------
178
179   void CGrid::addRelFileCompressed(const StdString& filename)
180   {
181      this->relFilesCompressed.insert(filename);
182   }
183
184   bool CGrid::isWrittenCompressed(const StdString& filename) const
185   {
186      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
187   }
188
189   //---------------------------------------------------------------
190
191   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
192   {
193     if (this->isDomainAxisChecked) return;
194
195     this->solveAxisRef(areAttributesChecked);
196     this->solveDomainRef(areAttributesChecked);
197     computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
198     this->isDomainAxisChecked = areAttributesChecked;
199   }
200
201   void CGrid::checkEligibilityForCompressedOutput()
202   {
203     // We don't check if the mask is valid here, just if a mask has been defined at this point.
204     isCompressible_ = !mask1.isEmpty() || !mask2.isEmpty() || !mask3.isEmpty();
205   }
206
207   void CGrid::checkMaskIndex(bool doSendingIndex)
208   {
209     CContext* context = CContext::getCurrent();
210     CContextClient* client=context->client;
211
212     if (isScalarGrid())
213     {
214       if (context->hasClient)
215          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
216
217       if (this->isChecked) return;
218       if (context->hasClient)
219       {
220          this->computeIndexScalarGrid();
221       }
222
223       this->isChecked = true;
224       return;
225     }
226
227     if (context->hasClient)
228      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
229
230     if (this->isChecked) return;
231
232     if (context->hasClient)
233     {
234        this->checkAttributesAfterTransformation();
235        this->checkMask();
236        this->computeIndex();
237     }
238     this->isChecked = true;
239   }
240
241   void CGrid::checkMask(void)
242   {
243      using namespace std;
244      std::vector<CDomain*> domainP = this->getDomains();
245      std::vector<CAxis*> axisP = this->getAxis();
246      int dim = domainP.size() * 2 + axisP.size();
247
248      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
249      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
250      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
251      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
252
253      switch (dim) {
254        case 1:
255          checkGridMask(mask1, domainMasks, axisMasks, axis_domain_order);
256          break;
257        case 2:
258          checkGridMask(mask2, domainMasks, axisMasks, axis_domain_order);
259          break;
260        case 3:
261          checkGridMask(mask3, domainMasks, axisMasks, axis_domain_order);
262          break;
263//        case 4:
264//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
265//          break;
266//        case 5:
267//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
268//          break;
269//        case 6:
270//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
271//          break;
272//        case 7:
273//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
274//          break;
275        default:
276          break;
277      }
278   }
279
280   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
281   {
282      using namespace std;
283      std::vector<CDomain*> domainP = this->getDomains();
284      std::vector<CAxis*> axisP = this->getAxis();
285      int dim = domainP.size() * 2 + axisP.size();
286
287      switch (dim) {
288        case 1:
289          modifyGridMask(mask1, indexToModify);
290          break;
291        case 2:
292          modifyGridMask(mask2, indexToModify);
293          break;
294        case 3:
295          modifyGridMask(mask3, indexToModify);
296          break;
297
298        default:
299          break;
300      }
301   }
302
303   //---------------------------------------------------------------
304
305   void CGrid::solveDomainRef(bool sendAtt)
306   {
307      setDomainList();
308      std::vector<CDomain*> domListP = this->getDomains();
309      if (!domListP.empty())
310      {
311        for (int i = 0; i < domListP.size(); ++i)
312        {
313          if (sendAtt) domListP[i]->sendCheckedAttributes();
314          else domListP[i]->checkAttributesOnClient();
315        }
316      }
317   }
318
319   //---------------------------------------------------------------
320
321   void CGrid::solveAxisRef(bool sendAtt)
322   {
323      setAxisList();
324      std::vector<CAxis*> axisListP = this->getAxis();
325      if (!axisListP.empty())
326      {
327        int idx = 0;
328        axisPositionInGrid_.resize(0);
329        for (int i = 0; i < axis_domain_order.numElements(); ++i)
330        {
331          if (false == axis_domain_order(i))
332          {
333            axisPositionInGrid_.push_back(idx);
334            ++idx;
335          }
336          else idx += 2;
337        }
338
339        for (int i = 0; i < axisListP.size(); ++i)
340        {
341          if (sendAtt)
342            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
343          else
344            axisListP[i]->checkAttributesOnClient();
345          ++idx;
346        }
347      }
348   }
349
350   std::vector<int> CGrid::getAxisPositionInGrid() const
351   {
352     return axisPositionInGrid_;
353   }
354
355   //---------------------------------------------------------------
356
357   void CGrid::computeIndex(void)
358   {
359     CContext* context = CContext::getCurrent();
360     CContextClient* client = context->client;
361
362     // First of all, compute distribution on client side
363     clientDistribution_ = new CDistributionClient(client->clientRank, this);
364     // Get local data index on client
365     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
366     int nbStoreIndex = storeIndex_client.numElements();
367     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
368     isDataDistributed_= clientDistribution_->isDataDistributed();
369
370     if (!doGridHaveDataDistributed())
371     {
372        if (0 == client->clientRank)
373        {
374          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
375          for (int rank = 0; rank < client->serverSize; ++rank)
376            connectedDataSize_[rank] = ssize;
377        }
378        return;
379     }
380
381     // Compute mapping between client and server
382     size_t globalSizeIndex = 1, indexBegin, indexEnd;
383     int range, clientSize = client->clientSize;
384     for (int i = 0; i < globalDim_.size(); ++i) globalSizeIndex *= globalDim_[i];
385     indexBegin = 0;
386     for (int i = 0; i < clientSize; ++i)
387     {
388       range = globalSizeIndex / clientSize;
389       if (i < (globalSizeIndex%clientSize)) ++range;
390       if (i == client->clientRank) break;
391       indexBegin += range;
392     }
393     indexEnd = indexBegin + range - 1;
394
395     // Then compute distribution on server side
396     CServerDistributionDescription serverDistributionDescription(globalDim_);
397     serverDistributionDescription.computeServerGlobalIndexInRange(client->serverSize,
398                                                                   std::make_pair<size_t,size_t>(indexBegin, indexEnd),
399                                                                   positionDimensionDistributed_);
400
401     // Finally, compute index mapping between client(s) and server(s)
402     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription.getGlobalIndexRange(),
403                                                            client->intraComm,
404                                                            clientDistribution_->isDataDistributed());
405
406     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex());
407     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
408
409     const std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
410     std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
411     itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
412     iteGlobalMap = globalIndexOnServer.end();
413
414     typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
415     std::vector<int>::iterator itVec;
416     int nbGlobalIndex = globalIndexSendToServer.size();
417     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
418     {
419       int serverRank = itGlobalMap->first;
420       int indexSize = itGlobalMap->second.size();
421       std::vector<int> permutIndex(indexSize);
422       XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
423       XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
424       BinarySearch binSearch(itGlobalMap->second);
425       for (int i = 0; i < nbGlobalIndex; ++i)
426       {
427         if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexSendToServer[i], itVec))
428         {
429           if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
430             connectedDataSize_[serverRank] = 1;
431           else
432             ++connectedDataSize_[serverRank];
433         }
434       }
435     }
436
437     connectedServerRank_.clear();
438     for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
439       connectedServerRank_.push_back(it->first);
440     }
441     if (!connectedDataSize_.empty())
442     {
443       connectedServerRank_.clear();
444       for (std::map<int,size_t>::const_iterator it = connectedDataSize_.begin(); it != connectedDataSize_.end(); ++it)
445         connectedServerRank_.push_back(it->first);
446     }
447
448     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
449   }
450
451   //----------------------------------------------------------------
452
453   CGrid* CGrid::createGrid(CDomain* domain)
454   {
455      std::vector<CDomain*> vecDom(1, domain);
456      std::vector<CAxis*> vecAxis;
457
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.