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

Last change on this file since 746 was 746, checked in by rlacroix, 9 years ago

Restore support for spatial transformations when 'domain_ref'/'axis_ref' are used.

  • 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)
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        if ((!pDom->domain_ref.isEmpty()) && (pDom->name.isEmpty()))
1227          pDom->name.setValue(pDom->getBaseDomainReference()->getId());
1228      }
1229    }
1230
1231    setAxisList();
1232    it = axisList_.begin(); itE = axisList_.end();
1233    for (; it != itE; ++it)
1234    {
1235      CAxis* pAxis = CAxis::get(*it);
1236      if (context->hasClient)
1237      {
1238        pAxis->solveRefInheritance(apply);
1239        pAxis->solveBaseReference();
1240        pAxis->solveInheritanceTransformation();
1241        if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
1242          pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
1243      }
1244    }
1245  }
1246
1247  bool CGrid::isTransformed()
1248  {
1249    return isTransformed_;
1250  }
1251
1252  void CGrid::setTransformed()
1253  {
1254    isTransformed_ = true;
1255  }
1256
1257  CGridTransformation* CGrid::getTransformations()
1258  {
1259    return transformations_;
1260  }
1261
1262  /*!
1263     Complete all the necessary (and lacking) attributes of a grid
1264     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1265  */
1266  void CGrid::completeGrid(CGrid* transformGridSrc)
1267  {
1268    if (!transformGridSrc)
1269      ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1270            << "Impossible to complete grid '" << getId() << "', the source grid is null.");
1271
1272    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1273    {
1274      ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1275           << "Two grids have different dimension size"
1276           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1277           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1278    }
1279    else
1280    {
1281      int ssize = axis_domain_order.numElements();
1282      for (int i = 0; i < ssize; ++i)
1283        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1284          ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1285                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1286                << " don't have elements in the same order");
1287    }
1288
1289    CGridGenerate gridGenerate(this, transformGridSrc);
1290    gridGenerate.completeGrid();
1291  }
1292
1293  void CGrid::transformGrid(CGrid* transformGridSrc)
1294  {
1295    if (!transformGridSrc)
1296      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1297            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1298
1299    if (isTransformed()) return;
1300    setTransformed();
1301    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1302    {
1303      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1304           << "Two grids have different dimension size"
1305           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1306           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1307    }
1308    else
1309    {
1310      int ssize = axis_domain_order.numElements();
1311      for (int i = 0; i < ssize; ++i)
1312        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1313          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1314                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1315                << " don't have elements in the same order");
1316    }
1317
1318    transformations_ = new CGridTransformation(this, transformGridSrc);
1319    transformations_->computeAll();
1320
1321    // Ok, now need to compute index of grid source
1322    transformGridSrc->checkMaskIndex(false);
1323  }
1324
1325  /*!
1326  \brief Get the list of domain pointers
1327  \return list of domain pointers
1328  */
1329  std::vector<CDomain*> CGrid::getDomains()
1330  {
1331    std::vector<CDomain*> domList;
1332    if (!domList_.empty())
1333    {
1334      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1335    }
1336    return domList;
1337  }
1338
1339  /*!
1340  \brief Get the list of  axis pointers
1341  \return list of axis pointers
1342  */
1343  std::vector<CAxis*> CGrid::getAxis()
1344  {
1345    std::vector<CAxis*> aList;
1346    if (!axisList_.empty())
1347      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1348
1349    return aList;
1350  }
1351
1352  /*!
1353  \brief Set domain(s) of a grid from a list
1354  \param[in] domains list of domains
1355  */
1356  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1357  {
1358    if (isDomListSet) return;
1359    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1360    if (!domains.empty() && domList.empty())
1361    {
1362      for (int i = 0; i < domains.size(); ++i)
1363        this->getVirtualDomainGroup()->addChild(domains[i]);
1364      domList = this->getVirtualDomainGroup()->getAllChildren();
1365    }
1366
1367    if (!domList.empty())
1368    {
1369      int sizeDom = domList.size();
1370      domList_.resize(sizeDom);
1371      for (int i = 0; i < sizeDom; ++i)
1372      {
1373        domList_[i] = domList[i]->getId();
1374      }
1375      isDomListSet = true;
1376    }
1377
1378  }
1379
1380  /*!
1381  \brief Set axis(s) of a grid from a list
1382  \param[in] axis list of axis
1383  */
1384  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1385  {
1386    if (isAxisListSet) return;
1387    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1388    if (!axis.empty() && aList.empty())
1389    {
1390      for (int i = 0; i < axis.size(); ++i)
1391        this->getVirtualAxisGroup()->addChild(axis[i]);
1392      aList = this->getVirtualAxisGroup()->getAllChildren();
1393    }
1394
1395    if (!aList.empty())
1396    {
1397      int sizeAxis = aList.size();
1398      axisList_.resize(sizeAxis);
1399      for (int i = 0; i < sizeAxis; ++i)
1400      {
1401        axisList_[i] = aList[i]->getId();
1402      }
1403      isAxisListSet = true;
1404    }
1405  }
1406
1407  /*!
1408  \brief Get list of id of domains
1409  \return id list of domains
1410  */
1411  std::vector<StdString> CGrid::getDomainList()
1412  {
1413    setDomainList();
1414    return domList_;
1415  }
1416
1417  /*!
1418  \brief Get list of id of axis
1419  \return id list of axis
1420  */
1421  std::vector<StdString> CGrid::getAxisList()
1422  {
1423    setAxisList();
1424    return axisList_;
1425  }
1426
1427  void CGrid::sendAllDomains()
1428  {
1429    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1430    int dSize = domList.size();
1431    for (int i = 0; i < dSize; ++i)
1432    {
1433      sendAddDomain(domList[i]->getId());
1434      domList[i]->sendAllAttributesToServer();
1435    }
1436  }
1437
1438  void CGrid::sendAllAxis()
1439  {
1440    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1441    int aSize = aList.size();
1442
1443    for (int i = 0; i < aSize; ++i)
1444    {
1445      sendAddAxis(aList[i]->getId());
1446      aList[i]->sendAllAttributesToServer();
1447    }
1448  }
1449
1450  void CGrid::parse(xml::CXMLNode& node)
1451  {
1452    SuperClass::parse(node);
1453
1454    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1455    std::vector<bool> order;
1456
1457    if (node.goToChildElement())
1458    {
1459      StdString domainName("domain");
1460      StdString axisName("axis");
1461      do
1462      {
1463        if (node.getElementName() == domainName) {
1464          order.push_back(true);
1465          this->getVirtualDomainGroup()->parseChild(node);
1466        }
1467        if (node.getElementName() == axisName) {
1468          order.push_back(false);
1469          this->getVirtualAxisGroup()->parseChild(node);
1470        }
1471      } while (node.goToNextElement());
1472      node.goToParentElement();
1473    }
1474
1475    if (!order.empty())
1476    {
1477      int sizeOrd = order.size();
1478      axis_domain_order.resize(sizeOrd);
1479      for (int i = 0; i < sizeOrd; ++i)
1480      {
1481        axis_domain_order(i) = order[i];
1482      }
1483    }
1484
1485    setDomainList();
1486    setAxisList();
1487   }
1488} // namespace xios
Note: See TracBrowser for help on using the repository browser.