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

Last change on this file since 831 was 831, checked in by mhnguyen, 5 years ago

Cleaning up some redundant coeds and making some improvements

+) Remove some XIOS Search to make code run faster
+) Remove some commented codes

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