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

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

Refactoring transformation code

+) On exchanging information during transformation, not only global index are sent but also local index
+) Correct a bug in distributed hash table (dht)
+) Add new type for dht
+) Clean up some redundant codes

Test
+) On Curie
+) Every test passes
+) Code runs faster in some cases (up to 30%)

  • 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.6 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 std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
462     CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
463     itGlobalMap  = itbGlobalMap = globalIndexOnServer.begin();
464     iteGlobalMap = globalIndexOnServer.end();
465
466     typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
467     std::vector<int>::iterator itVec;
468     int nbGlobalIndex = globalIndexSendToServer.size();
469     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
470     {
471       int serverRank = itGlobalMap->first;
472       int indexSize = itGlobalMap->second.size();
473       std::vector<int> permutIndex(indexSize);
474       XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
475       XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
476       BinarySearch binSearch(itGlobalMap->second);
477       for (int i = 0; i < nbGlobalIndex; ++i)
478       {
479         if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexSendToServer[i], itVec))
480         {
481           if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
482             connectedDataSize_[serverRank] = 1;
483           else
484             ++connectedDataSize_[serverRank];
485         }
486       }
487     }
488
489     connectedServerRank_.clear();
490     for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
491       connectedServerRank_.push_back(itGlobalMap->first);
492     }
493
494     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
495   }
496
497   //----------------------------------------------------------------
498
499   CGrid* CGrid::createGrid(CDomain* domain)
500   {
501      std::vector<CDomain*> vecDom(1, domain);
502      std::vector<CAxis*> vecAxis;
503
504      return createGrid(vecDom, vecAxis);
505   }
506
507   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
508   {
509      std::vector<CDomain*> vecDom(1, domain);
510      std::vector<CAxis*> vecAxis(1, axis);
511
512      return createGrid(vecDom, vecAxis);
513   }
514
515   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
516                            const CArray<bool,1>& axisDomainOrder)
517   {
518      return createGrid(generateId(domains, axis, axisDomainOrder), domains, axis, axisDomainOrder);
519   }
520
521   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
522                            const CArray<bool,1>& axisDomainOrder)
523   {
524      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size()))
525        ERROR("CGrid* CGrid::createGrid(...)",
526              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
527              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
528
529      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
530      grid->setDomainList(domains);
531      grid->setAxisList(axis);
532
533      // By default, domains are always the first elements of a grid
534      if (0 == axisDomainOrder.numElements())
535      {
536        int size = domains.size() + axis.size();
537        grid->axis_domain_order.resize(size);
538        for (int i = 0; i < size; ++i)
539        {
540          if (i < domains.size()) grid->axis_domain_order(i) = true;
541          else grid->axis_domain_order(i) = false;
542        }
543      }
544      else
545      {
546        grid->axis_domain_order.resize(axisDomainOrder.numElements());
547        grid->axis_domain_order = axisDomainOrder;
548      }
549
550      grid->solveDomainAxisRefInheritance(true);
551
552      return grid;
553   }
554
555   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
556   {
557     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
558     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
559     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
560     {
561       CAxis* axis = CAxis::createAxis();
562       axis->duplicateAttributes(axisSrcTmp[idx]);
563       axis->duplicateTransformation(axisSrcTmp[idx]);
564       axis->solveRefInheritance(true);
565       axis->solveInheritanceTransformation();
566       axisSrc.push_back(axis);
567     }
568
569     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
570     {
571       CDomain* domain = CDomain::createDomain();
572       domain->duplicateAttributes(domainSrcTmp[idx]);
573       domain->duplicateTransformation(domainSrcTmp[idx]);
574       domain->solveRefInheritance(true);
575       domain->solveInheritanceTransformation();
576       domainSrc.push_back(domain);
577     }
578
579      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, gridSrc->axis_domain_order);
580
581      return grid;
582   }
583
584   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
585                               const CArray<bool,1>& axisDomainOrder)
586   {
587      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size()))
588        ERROR("CGrid* CGrid::generateId(...)",
589              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
590              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
591
592      std::ostringstream id;
593
594      if (domains.empty() && axis.empty())
595        id << "__scalar_grid__";
596      else
597      {
598        id << "__grid";
599
600        if (0 == axisDomainOrder.numElements())
601        {
602          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
603          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
604        }
605        else
606        {
607          size_t iDomain = 0, iAxis = 0;
608          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
609          {
610            if (axisDomainOrder(i))
611              id << "_" << domains[iDomain++]->getId();
612            else
613              id << "_" << axis[iAxis++]->getId();
614          }
615        }
616
617        id << "__";
618      }
619
620      return id.str();
621   }
622
623   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
624   {
625     StdString idSrc  = gridSrc->getId();
626     StdString idDest = gridDest->getId();
627
628     std::ostringstream id;
629     id << idSrc << "__" << idDest;
630
631     return id.str();
632   }
633
634   //----------------------------------------------------------------
635
636   CDomainGroup* CGrid::getVirtualDomainGroup() const
637   {
638     return this->vDomainGroup_;
639   }
640
641   CAxisGroup* CGrid::getVirtualAxisGroup() const
642   {
643     return this->vAxisGroup_;
644   }
645
646   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
647   {
648     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
649     StdSize numElements = stored.numElements();
650     for (StdSize n = 0; n < numElements; ++n)
651     {
652       field[out_i(n)] = stored(n);
653     }
654   }
655
656   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
657   {
658     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
659     StdSize numElements = stored.numElements();
660     for (StdSize n = 0; n < numElements; ++n)
661     {
662       stored(n) = field[out_i(n)];
663     }
664   }
665
666   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
667   {
668     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
669     StdSize numElements = stored.numElements();
670     for (StdSize n = 0; n < numElements; ++n)
671     {
672       field[out_i(n)] = stored(n);
673     }
674   }
675
676   //----------------------------------------------------------------
677
678   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
679   {
680      const StdSize size = storeIndex_client.numElements();
681
682      stored.resize(size);
683      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
684   }
685
686   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
687   {
688      const StdSize size = storeIndex_client.numElements();
689
690      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
691   }
692
693  void CGrid::computeIndexScalarGrid()
694  {
695    CContext* context = CContext::getCurrent();
696    CContextClient* client=context->client;
697
698    storeIndex_client.resize(1);
699    storeIndex_client[0] = 0;
700    if (0 == client->clientRank)
701    {
702      for (int rank = 0; rank < client->serverSize; ++rank)
703        connectedDataSize_[rank] = 1;
704    }
705    isDataDistributed_ = false;
706  }
707
708  void CGrid::computeCompressedIndex()
709  {
710    compressedOutIndexFromClient = outIndexFromClient;
711
712    std::map<size_t, size_t> indexes;
713
714    {
715      std::map<int, CArray<size_t,1> >::const_iterator it = compressedOutIndexFromClient.begin();
716      std::map<int, CArray<size_t,1> >::const_iterator itEnd = compressedOutIndexFromClient.end();
717      for (; it != itEnd; ++it)
718      {
719        for (int i = 0; i < it->second.numElements(); ++i)
720          indexes.insert(std::make_pair(it->second(i), 0));
721      }
722    }
723
724    {
725      std::map<size_t, size_t>::iterator it = indexes.begin();
726      std::map<size_t, size_t>::iterator itEnd = indexes.end();
727      for (size_t i = 0; it != itEnd; ++it, ++i)
728        it->second = i;
729    }
730
731    {
732      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
733      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
734      for (; it != itEnd; ++it)
735      {
736        for (int i = 0; i < it->second.numElements(); ++i)
737          it->second(i) = indexes[it->second(i)];
738      }
739    }
740  }
741
742  void CGrid::sendIndexScalarGrid()
743  {
744    CContext* context = CContext::getCurrent();
745    CContextClient* client = context->client;
746
747    CEventClient event(getType(), EVENT_ID_INDEX);
748    list<CMessage> listMsg;
749    list<CArray<size_t,1> > listOutIndex;
750
751    if (0 == client->clientRank)
752    {
753      for (int rank = 0; rank < client->serverSize; ++rank)
754      {
755        int nb = 1;
756        storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(nb)));
757        listOutIndex.push_back(CArray<size_t,1>(nb));
758
759        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
760        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
761
762        for (int k = 0; k < nb; ++k)
763        {
764          outGlobalIndexOnServer(k) = 0;
765          outLocalIndexToServer(k)  = 0;
766        }
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
780  void CGrid::sendIndex(void)
781  {
782    CContext* context = CContext::getCurrent();
783    CContextClient* client = context->client;
784
785    CEventClient event(getType(), EVENT_ID_INDEX);
786    int rank;
787    list<CMessage> listMsg;
788    list<CArray<size_t,1> > listOutIndex;
789    const CClientServerMapping::GlobalIndexMap& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
790    const std::vector<int>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
791    const std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
792
793    if (!doGridHaveDataDistributed())
794    {
795      if (0 == client->clientRank)
796      {
797        CArray<size_t,1> outGlobalIndexOnServer(globalIndexSendToServer.size());
798        for (int idx = 0; idx < globalIndexSendToServer.size();++idx)
799          outGlobalIndexOnServer(idx) = globalIndexSendToServer[idx];
800
801        CArray<int,1> outLocalIndexToServer(localIndexSendToServer.size());
802        for (int idx = 0; idx < localIndexSendToServer.size();++idx)
803          outLocalIndexToServer(idx) = localIndexSendToServer[idx];
804
805        for (rank = 0; rank < client->serverSize; ++rank)
806        {
807          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
808          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
809
810          listMsg.push_back(CMessage());
811          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
812
813          event.push(rank, 1, listMsg.back());
814        }
815
816        client->sendEvent(event);
817      }
818      else
819        client->sendEvent(event);
820    }
821    else
822    {
823      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
824      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
825      iteGlobalMap = globalIndexOnServer.end();
826
827      int nbGlobalIndex = globalIndexSendToServer.size();
828      std::map<int,std::vector<int> >localIndexTmp;
829      std::map<int,std::vector<size_t> > globalIndexTmp;
830
831      typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
832      std::vector<int>::iterator itVec;
833      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
834      {
835        int serverRank = itGlobalMap->first;
836        int indexSize = itGlobalMap->second.size();
837        std::vector<int> permutIndex(indexSize);
838        XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
839        XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
840        BinarySearch binSearch(itGlobalMap->second);
841
842        for (int i = 0; i < nbGlobalIndex; ++i)
843        {
844          if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexSendToServer[i], itVec))
845          {
846            globalIndexTmp[serverRank].push_back(globalIndexSendToServer[i]);
847            localIndexTmp[serverRank].push_back(localIndexSendToServer[i]);
848          }
849        }
850      }
851
852      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
853      {
854        rank = connectedServerRank_[ns];
855        int nb = 0;
856        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
857          nb = globalIndexTmp[rank].size();
858
859        storeIndex_toSrv.insert(make_pair(rank, CArray<int,1>(nb)));
860        listOutIndex.push_back(CArray<size_t,1>(nb));
861
862        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
863        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
864
865        for (int k = 0; k < nb; ++k)
866        {
867          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
868          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
869        }
870
871        listMsg.push_back(CMessage());
872        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
873
874        event.push(rank, nbSenders[rank], listMsg.back());
875      }
876
877      client->sendEvent(event);
878    }
879  }
880
881  void CGrid::recvIndex(CEventServer& event)
882  {
883    string gridId;
884    vector<int> ranks;
885    vector<CBufferIn*> buffers;
886
887    list<CEventServer::SSubEvent>::iterator it;
888    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
889    {
890      ranks.push_back(it->rank);
891      CBufferIn* buffer = it->buffer;
892      *buffer >> gridId;
893      buffers.push_back(buffer);
894    }
895    get(gridId)->recvIndex(ranks, buffers);
896  }
897
898  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
899                                         const std::vector<CAxis*>& axis,
900                                         const CArray<bool,1>& axisDomainOrder)
901  {
902    globalDim_.resize(domains.size()*2+axis.size());
903    int idx = 0, idxDomain = 0, idxAxis = 0;
904    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
905    {
906      if (axisDomainOrder(i))
907      {
908        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
909        {
910          positionDimensionDistributed_ = idx;
911        }
912        else
913        {
914          positionDimensionDistributed_ = idx +1;
915        }
916
917        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
918        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
919
920        ++idxDomain;
921        idx += 2;
922      }
923      else
924      {
925        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
926        ++idxAxis;
927        ++idx;
928      }
929    }
930  }
931
932  std::vector<int> CGrid::getGlobalDimension()
933  {
934    return globalDim_;
935  }
936
937  bool CGrid::isScalarGrid() const
938  {
939    return (axisList_.empty() && domList_.empty());
940  }
941
942  /*!
943    Verify whether one server need to write data
944    There are some cases on which one server has nodata to write. For example, when we
945    just only want to zoom on a domain.
946  */
947  bool CGrid::doGridHaveDataToWrite()
948  {
949     return (0 != writtenDataSize_);
950  }
951
952  /*!
953    Return size of data which is written on each server
954    Whatever dimension of a grid, data which are written on server must be presented as
955    an one dimension array.
956    \return size of data written on server
957  */
958  size_t CGrid::getWrittenDataSize() const
959  {
960    return writtenDataSize_;
961  }
962
963  /*!
964    Returns the number of indexes written by each server.
965    \return the number of indexes written by each server
966  */
967  int CGrid::getNumberWrittenIndexes() const
968  {
969    return numberWrittenIndexes_;
970  }
971
972  /*!
973    Returns the total number of indexes written by the servers.
974    \return the total number of indexes written by the servers
975  */
976  int CGrid::getTotalNumberWrittenIndexes() const
977  {
978    return totalNumberWrittenIndexes_;
979  }
980
981  /*!
982    Returns the offset of indexes written by each server.
983    \return the offset of indexes written by each server
984  */
985  int CGrid::getOffsetWrittenIndexes() const
986  {
987    return offsetWrittenIndexes_;
988  }
989
990  const CDistributionServer* CGrid::getDistributionServer() const
991  {
992    return serverDistribution_;
993  }
994
995  const CDistributionClient* CGrid::getDistributionClient() const
996  {
997    return clientDistribution_;
998  }
999
1000  bool CGrid::doGridHaveDataDistributed()
1001  {
1002    if (isScalarGrid()) return false;
1003    else
1004      return isDataDistributed_;
1005  }
1006
1007  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1008  {
1009    CContext* context = CContext::getCurrent();
1010    CContextServer* server = context->server;
1011    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
1012    connectedServerRank_ = ranks;
1013
1014    for (int n = 0; n < ranks.size(); n++)
1015    {
1016      int rank = ranks[n];
1017      CBufferIn& buffer = *buffers[n];
1018
1019      buffer >> isDataDistributed_ >> isCompressible_;
1020      size_t dataSize = 0;
1021
1022      if (isScalarGrid())
1023      {
1024        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
1025        CArray<size_t,1> outIndex;
1026        buffer >> outIndex;
1027        outIndexFromClient.insert(std::make_pair(rank, outIndex));
1028        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
1029        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1030                                                      nZoomBeginGlobal, nGlob);
1031        return;
1032      }
1033
1034      if (0 == serverDistribution_)
1035      {
1036        int idx = 0, numElement = axis_domain_order.numElements();
1037        int ssize = numElement;
1038        std::vector<int> indexMap(numElement);
1039        for (int i = 0; i < numElement; ++i)
1040        {
1041          indexMap[i] = idx;
1042          if (true == axis_domain_order(i))
1043          {
1044            ++ssize;
1045            idx += 2;
1046          }
1047          else
1048            ++idx;
1049        }
1050
1051        int axisId = 0, domainId = 0;
1052        std::vector<CDomain*> domainList = getDomains();
1053        std::vector<CAxis*> axisList = getAxis();
1054        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
1055        for (int i = 0; i < numElement; ++i)
1056        {
1057          if (axis_domain_order(i))
1058          {
1059            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
1060            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
1061            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
1062            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1063
1064            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
1065            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
1066            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
1067            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1068            ++domainId;
1069          }
1070          else
1071          {
1072            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1073            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1074            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
1075            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1076            ++axisId;
1077          }
1078        }
1079        dataSize = 1;
1080        for (int i = 0; i < nZoomSize.size(); ++i)
1081          dataSize *= nZoomSize[i];
1082
1083        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1084                                                      nZoomBeginGlobal, nGlob);
1085      }
1086
1087      CArray<size_t,1> outIndex;
1088      buffer >> outIndex;
1089      if (isDataDistributed_)
1090        serverDistribution_->computeLocalIndex(outIndex);
1091      else
1092      {
1093        dataSize = outIndex.numElements();
1094        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
1095      }
1096      writtenDataSize_ += dataSize;
1097
1098      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1099      connectedDataSize_[rank] = outIndex.numElements();
1100      numberWrittenIndexes_ += outIndex.numElements();
1101    }
1102
1103    if (isDataDistributed_)
1104    {
1105      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1106      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1107      offsetWrittenIndexes_ -= numberWrittenIndexes_;
1108    }
1109    else
1110      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1111
1112    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1113  }
1114
1115   /*!
1116   \brief Dispatch event received from client
1117      Whenever a message is received in buffer of server, it will be processed depending on
1118   its event type. A new event type should be added in the switch list to make sure
1119   it processed on server side.
1120   \param [in] event: Received message
1121   */
1122  bool CGrid::dispatchEvent(CEventServer& event)
1123  {
1124
1125    if (SuperClass::dispatchEvent(event)) return true;
1126    else
1127    {
1128      switch(event.type)
1129      {
1130        case EVENT_ID_INDEX :
1131          recvIndex(event);
1132          return true;
1133          break;
1134
1135         case EVENT_ID_ADD_DOMAIN :
1136           recvAddDomain(event);
1137           return true;
1138           break;
1139
1140         case EVENT_ID_ADD_AXIS :
1141           recvAddAxis(event);
1142           return true;
1143           break;
1144        default :
1145          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1146                << "Unknown Event");
1147          return false;
1148      }
1149    }
1150  }
1151
1152   ///---------------------------------------------------------------
1153
1154   CDomain* CGrid::addDomain(const std::string& id)
1155   {
1156     return vDomainGroup_->createChild(id);
1157   }
1158
1159   CAxis* CGrid::addAxis(const std::string& id)
1160   {
1161     return vAxisGroup_->createChild(id);
1162   }
1163
1164   //! Change virtual field group to a new one
1165   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1166   {
1167      this->vDomainGroup_ = newVDomainGroup;
1168   }
1169
1170   //! Change virtual variable group to new one
1171   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1172   {
1173      this->vAxisGroup_ = newVAxisGroup;
1174   }
1175
1176   //----------------------------------------------------------------
1177   //! Create virtual field group, which is done normally on initializing file
1178   void CGrid::setVirtualDomainGroup(void)
1179   {
1180      this->setVirtualDomainGroup(CDomainGroup::create());
1181   }
1182
1183   //! Create virtual variable group, which is done normally on initializing file
1184   void CGrid::setVirtualAxisGroup(void)
1185   {
1186      this->setVirtualAxisGroup(CAxisGroup::create());
1187   }
1188
1189   /*!
1190   \brief Send a message to create a domain on server side
1191   \param[in] id String identity of domain that will be created on server
1192   */
1193   void CGrid::sendAddDomain(const string& id)
1194   {
1195    CContext* context=CContext::getCurrent();
1196
1197    if (! context->hasServer )
1198    {
1199       CContextClient* client=context->client;
1200
1201       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1202       if (client->isServerLeader())
1203       {
1204         CMessage msg;
1205         msg<<this->getId();
1206         msg<<id;
1207         const std::list<int>& ranks = client->getRanksServerLeader();
1208         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1209           event.push(*itRank,1,msg);
1210         client->sendEvent(event);
1211       }
1212       else client->sendEvent(event);
1213    }
1214   }
1215
1216   /*!
1217   \brief Send a message to create an axis on server side
1218   \param[in] id String identity of axis that will be created on server
1219   */
1220   void CGrid::sendAddAxis(const string& id)
1221   {
1222    CContext* context=CContext::getCurrent();
1223
1224    if (! context->hasServer )
1225    {
1226       CContextClient* client=context->client;
1227
1228       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1229       if (client->isServerLeader())
1230       {
1231         CMessage msg;
1232         msg<<this->getId();
1233         msg<<id;
1234         const std::list<int>& ranks = client->getRanksServerLeader();
1235         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1236           event.push(*itRank,1,msg);
1237         client->sendEvent(event);
1238       }
1239       else client->sendEvent(event);
1240    }
1241   }
1242
1243   /*!
1244   \brief Receive a message annoucing the creation of a domain on server side
1245   \param[in] event Received event
1246   */
1247   void CGrid::recvAddDomain(CEventServer& event)
1248   {
1249
1250      CBufferIn* buffer = event.subEvents.begin()->buffer;
1251      string id;
1252      *buffer >> id;
1253      get(id)->recvAddDomain(*buffer);
1254   }
1255
1256   /*!
1257   \brief Receive a message annoucing the creation of a domain on server side
1258   \param[in] buffer Buffer containing message
1259   */
1260   void CGrid::recvAddDomain(CBufferIn& buffer)
1261   {
1262      string id;
1263      buffer >> id;
1264      addDomain(id);
1265   }
1266
1267   /*!
1268   \brief Receive a message annoucing the creation of an axis on server side
1269   \param[in] event Received event
1270   */
1271   void CGrid::recvAddAxis(CEventServer& event)
1272   {
1273
1274      CBufferIn* buffer = event.subEvents.begin()->buffer;
1275      string id;
1276      *buffer >> id;
1277      get(id)->recvAddAxis(*buffer);
1278   }
1279
1280   /*!
1281   \brief Receive a message annoucing the creation of an axis on server side
1282   \param[in] buffer Buffer containing message
1283   */
1284   void CGrid::recvAddAxis(CBufferIn& buffer)
1285   {
1286      string id;
1287      buffer >> id;
1288      addAxis(id);
1289   }
1290
1291  /*!
1292  \brief Solve domain and axis references
1293  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1294  all attributes from their parents, they should be processed with this function
1295  \param[in] apply inherit all attributes of parents (true)
1296  */
1297  void CGrid::solveDomainAxisRefInheritance(bool apply)
1298  {
1299    CContext* context = CContext::getCurrent();
1300    unsigned int vecSize, i;
1301    std::vector<StdString>::iterator it, itE;
1302    setDomainList();
1303    it = domList_.begin(); itE = domList_.end();
1304    for (; it != itE; ++it)
1305    {
1306      CDomain* pDom = CDomain::get(*it);
1307      if (context->hasClient)
1308      {
1309        pDom->solveRefInheritance(apply);
1310        pDom->solveInheritanceTransformation();
1311      }
1312    }
1313
1314    setAxisList();
1315    it = axisList_.begin(); itE = axisList_.end();
1316    for (; it != itE; ++it)
1317    {
1318      CAxis* pAxis = CAxis::get(*it);
1319      if (context->hasClient)
1320      {
1321        pAxis->solveRefInheritance(apply);
1322        pAxis->solveInheritanceTransformation();
1323      }
1324    }
1325  }
1326
1327  bool CGrid::isTransformed()
1328  {
1329    return isTransformed_;
1330  }
1331
1332  void CGrid::setTransformed()
1333  {
1334    isTransformed_ = true;
1335  }
1336
1337  CGridTransformation* CGrid::getTransformations()
1338  {
1339    return transformations_;
1340  }
1341
1342  void CGrid::addTransGridSource(CGrid* gridSrc)
1343  {
1344    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1345      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1346  }
1347
1348  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1349  {
1350    return gridSrc_;
1351  }
1352
1353  /*!
1354     Complete all the necessary (and lacking) attributes of a grid
1355     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1356  */
1357  void CGrid::completeGrid(CGrid* transformGridSrc)
1358  {
1359    if (0 != transformGridSrc)
1360    {
1361      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1362      {
1363        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1364             << "Two grids have different dimension size"
1365             << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1366             << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1367      }
1368      else
1369      {
1370        int ssize = axis_domain_order.numElements();
1371        for (int i = 0; i < ssize; ++i)
1372          if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1373            ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1374                  << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1375                  << " don't have elements in the same order");
1376      }
1377    }
1378
1379    CGridGenerate gridGenerate(this, transformGridSrc);
1380    gridGenerate.completeGrid();
1381  }
1382
1383  void CGrid::transformGrid(CGrid* transformGridSrc)
1384  {
1385    if (!transformGridSrc)
1386      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1387            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1388
1389    if (isTransformed()) return;
1390    setTransformed();
1391    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1392    {
1393      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1394           << "Two grids have different dimension size"
1395           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1396           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1397    }
1398    else
1399    {
1400      int ssize = axis_domain_order.numElements();
1401      for (int i = 0; i < ssize; ++i)
1402        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1403          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1404                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1405                << " don't have elements in the same order");
1406    }
1407
1408    transformations_ = new CGridTransformation(this, transformGridSrc);
1409    transformations_->computeAll();
1410    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1411
1412    // Ok, now need to compute index of grid source
1413    transformGridSrc->checkMaskIndex(false);
1414  }
1415
1416  bool CGrid::hasTransform()
1417  {
1418    return hasTransform_;
1419  }
1420
1421  /*!
1422  \brief Get the list of domain pointers
1423  \return list of domain pointers
1424  */
1425  std::vector<CDomain*> CGrid::getDomains()
1426  {
1427    std::vector<CDomain*> domList;
1428    if (!domList_.empty())
1429    {
1430      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1431    }
1432    return domList;
1433  }
1434
1435  /*!
1436  \brief Get the list of  axis pointers
1437  \return list of axis pointers
1438  */
1439  std::vector<CAxis*> CGrid::getAxis()
1440  {
1441    std::vector<CAxis*> aList;
1442    if (!axisList_.empty())
1443      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1444
1445    return aList;
1446  }
1447
1448  /*!
1449  \brief Set domain(s) of a grid from a list
1450  \param[in] domains list of domains
1451  */
1452  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1453  {
1454    if (isDomListSet) return;
1455    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1456    if (!domains.empty() && domList.empty())
1457    {
1458      for (int i = 0; i < domains.size(); ++i)
1459        this->getVirtualDomainGroup()->addChild(domains[i]);
1460      domList = this->getVirtualDomainGroup()->getAllChildren();
1461    }
1462
1463    if (!domList.empty())
1464    {
1465      int sizeDom = domList.size();
1466      domList_.resize(sizeDom);
1467      for (int i = 0; i < sizeDom; ++i)
1468      {
1469        domList_[i] = domList[i]->getId();
1470      }
1471      isDomListSet = true;
1472    }
1473
1474  }
1475
1476  /*!
1477  \brief Set axis(s) of a grid from a list
1478  \param[in] axis list of axis
1479  */
1480  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1481  {
1482    if (isAxisListSet) return;
1483    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1484    if (!axis.empty() && aList.empty())
1485    {
1486      for (int i = 0; i < axis.size(); ++i)
1487        this->getVirtualAxisGroup()->addChild(axis[i]);
1488      aList = this->getVirtualAxisGroup()->getAllChildren();
1489    }
1490
1491    if (!aList.empty())
1492    {
1493      int sizeAxis = aList.size();
1494      axisList_.resize(sizeAxis);
1495      for (int i = 0; i < sizeAxis; ++i)
1496      {
1497        axisList_[i] = aList[i]->getId();
1498      }
1499      isAxisListSet = true;
1500    }
1501  }
1502
1503  /*!
1504  \brief Get list of id of domains
1505  \return id list of domains
1506  */
1507  std::vector<StdString> CGrid::getDomainList()
1508  {
1509    setDomainList();
1510    return domList_;
1511  }
1512
1513  /*!
1514  \brief Get list of id of axis
1515  \return id list of axis
1516  */
1517  std::vector<StdString> CGrid::getAxisList()
1518  {
1519    setAxisList();
1520    return axisList_;
1521  }
1522
1523  void CGrid::sendAllDomains()
1524  {
1525    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1526    int dSize = domList.size();
1527    for (int i = 0; i < dSize; ++i)
1528    {
1529      sendAddDomain(domList[i]->getId());
1530      domList[i]->sendAllAttributesToServer();
1531    }
1532  }
1533
1534  void CGrid::sendAllAxis()
1535  {
1536    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1537    int aSize = aList.size();
1538
1539    for (int i = 0; i < aSize; ++i)
1540    {
1541      sendAddAxis(aList[i]->getId());
1542      aList[i]->sendAllAttributesToServer();
1543    }
1544  }
1545
1546  void CGrid::parse(xml::CXMLNode& node)
1547  {
1548    SuperClass::parse(node);
1549
1550    // List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false)
1551    std::vector<bool> order;
1552
1553    if (node.goToChildElement())
1554    {
1555      StdString domainName("domain");
1556      StdString axisName("axis");
1557      do
1558      {
1559        if (node.getElementName() == domainName) {
1560          order.push_back(true);
1561          this->getVirtualDomainGroup()->parseChild(node);
1562        }
1563        if (node.getElementName() == axisName) {
1564          order.push_back(false);
1565          this->getVirtualAxisGroup()->parseChild(node);
1566        }
1567      } while (node.goToNextElement());
1568      node.goToParentElement();
1569    }
1570
1571    if (!order.empty())
1572    {
1573      int sizeOrd = order.size();
1574      axis_domain_order.resize(sizeOrd);
1575      for (int i = 0; i < sizeOrd; ++i)
1576      {
1577        axis_domain_order(i) = order[i];
1578      }
1579    }
1580
1581    setDomainList();
1582    setAxisList();
1583   }
1584} // namespace xios
Note: See TracBrowser for help on using the repository browser.