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

Last change on this file since 817 was 817, checked in by mhnguyen, 8 years ago

Adding some attributes for axis and grid (ticket 71, 78)

+) Add index attribute for axis
+) Change mask?d to mask_?d for grid

Test
+) On Curie
+) Test passes

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