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

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

Making some improvements of transformation algorithm

+) Correct the way to enlisting transformations in an element (domain, axis)
+) Optimize generic transformation to make sure temporary grid to be created on demand
+) Update some mpi tag to prevent conflict
+) Correct some minor stuffs
+) Update documents

Test
+) On Curie
+) all test pass

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