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

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

Exposing some functions to Fortran interface

+) Allow add axis and domain into grid with Fortran interface
+) Remove some redundant code

Test
+) On Curie
+) test_client passes

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 49.3 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), order_()
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), order_()
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  CDistributionServer* CGrid::getDistributionServer()
982  {
983    return serverDistribution_;
984  }
985
986  CDistributionClient* CGrid::getDistributionClient()
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     order_.push_back(true);
1148     axis_domain_order.resize(order_.size());
1149     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1150     return vDomainGroup_->createChild(id);
1151   }
1152
1153   CAxis* CGrid::addAxis(const std::string& id)
1154   {
1155     order_.push_back(false);
1156     axis_domain_order.resize(order_.size());
1157     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1158     return vAxisGroup_->createChild(id);
1159   }
1160
1161   //! Change virtual field group to a new one
1162   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1163   {
1164      this->vDomainGroup_ = newVDomainGroup;
1165   }
1166
1167   //! Change virtual variable group to new one
1168   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1169   {
1170      this->vAxisGroup_ = newVAxisGroup;
1171   }
1172
1173   //----------------------------------------------------------------
1174   //! Create virtual field group, which is done normally on initializing file
1175   void CGrid::setVirtualDomainGroup(void)
1176   {
1177      this->setVirtualDomainGroup(CDomainGroup::create());
1178   }
1179
1180   //! Create virtual variable group, which is done normally on initializing file
1181   void CGrid::setVirtualAxisGroup(void)
1182   {
1183      this->setVirtualAxisGroup(CAxisGroup::create());
1184   }
1185
1186   /*!
1187   \brief Send a message to create a domain on server side
1188   \param[in] id String identity of domain that will be created on server
1189   */
1190   void CGrid::sendAddDomain(const string& id)
1191   {
1192    CContext* context=CContext::getCurrent();
1193
1194    if (! context->hasServer )
1195    {
1196       CContextClient* client=context->client;
1197
1198       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1199       if (client->isServerLeader())
1200       {
1201         CMessage msg;
1202         msg<<this->getId();
1203         msg<<id;
1204         const std::list<int>& ranks = client->getRanksServerLeader();
1205         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1206           event.push(*itRank,1,msg);
1207         client->sendEvent(event);
1208       }
1209       else client->sendEvent(event);
1210    }
1211   }
1212
1213   /*!
1214   \brief Send a message to create an axis on server side
1215   \param[in] id String identity of axis that will be created on server
1216   */
1217   void CGrid::sendAddAxis(const string& id)
1218   {
1219    CContext* context=CContext::getCurrent();
1220
1221    if (! context->hasServer )
1222    {
1223       CContextClient* client=context->client;
1224
1225       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1226       if (client->isServerLeader())
1227       {
1228         CMessage msg;
1229         msg<<this->getId();
1230         msg<<id;
1231         const std::list<int>& ranks = client->getRanksServerLeader();
1232         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1233           event.push(*itRank,1,msg);
1234         client->sendEvent(event);
1235       }
1236       else client->sendEvent(event);
1237    }
1238   }
1239
1240   /*!
1241   \brief Receive a message annoucing the creation of a domain on server side
1242   \param[in] event Received event
1243   */
1244   void CGrid::recvAddDomain(CEventServer& event)
1245   {
1246
1247      CBufferIn* buffer = event.subEvents.begin()->buffer;
1248      string id;
1249      *buffer >> id;
1250      get(id)->recvAddDomain(*buffer);
1251   }
1252
1253   /*!
1254   \brief Receive a message annoucing the creation of a domain on server side
1255   \param[in] buffer Buffer containing message
1256   */
1257   void CGrid::recvAddDomain(CBufferIn& buffer)
1258   {
1259      string id;
1260      buffer >> id;
1261      addDomain(id);
1262   }
1263
1264   /*!
1265   \brief Receive a message annoucing the creation of an axis on server side
1266   \param[in] event Received event
1267   */
1268   void CGrid::recvAddAxis(CEventServer& event)
1269   {
1270
1271      CBufferIn* buffer = event.subEvents.begin()->buffer;
1272      string id;
1273      *buffer >> id;
1274      get(id)->recvAddAxis(*buffer);
1275   }
1276
1277   /*!
1278   \brief Receive a message annoucing the creation of an axis on server side
1279   \param[in] buffer Buffer containing message
1280   */
1281   void CGrid::recvAddAxis(CBufferIn& buffer)
1282   {
1283      string id;
1284      buffer >> id;
1285      addAxis(id);
1286   }
1287
1288  /*!
1289  \brief Solve domain and axis references
1290  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1291  all attributes from their parents, they should be processed with this function
1292  \param[in] apply inherit all attributes of parents (true)
1293  */
1294  void CGrid::solveDomainAxisRefInheritance(bool apply)
1295  {
1296    CContext* context = CContext::getCurrent();
1297    unsigned int vecSize, i;
1298    std::vector<StdString>::iterator it, itE;
1299    setDomainList();
1300    it = domList_.begin(); itE = domList_.end();
1301    for (; it != itE; ++it)
1302    {
1303      CDomain* pDom = CDomain::get(*it);
1304      if (context->hasClient)
1305      {
1306        pDom->solveRefInheritance(apply);
1307        pDom->solveInheritanceTransformation();
1308      }
1309    }
1310
1311    setAxisList();
1312    it = axisList_.begin(); itE = axisList_.end();
1313    for (; it != itE; ++it)
1314    {
1315      CAxis* pAxis = CAxis::get(*it);
1316      if (context->hasClient)
1317      {
1318        pAxis->solveRefInheritance(apply);
1319        pAxis->solveInheritanceTransformation();
1320      }
1321    }
1322  }
1323
1324  bool CGrid::isTransformed()
1325  {
1326    return isTransformed_;
1327  }
1328
1329  void CGrid::setTransformed()
1330  {
1331    isTransformed_ = true;
1332  }
1333
1334  CGridTransformation* CGrid::getTransformations()
1335  {
1336    return transformations_;
1337  }
1338
1339  void CGrid::addTransGridSource(CGrid* gridSrc)
1340  {
1341    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1342      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1343  }
1344
1345  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1346  {
1347    return gridSrc_;
1348  }
1349
1350  /*!
1351     Complete all the necessary (and lacking) attributes of a grid
1352     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1353  */
1354  void CGrid::completeGrid(CGrid* transformGridSrc)
1355  {
1356    if (0 != transformGridSrc)
1357    {
1358      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1359      {
1360        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1361             << "Two grids have different dimension size"
1362             << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1363             << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1364      }
1365      else
1366      {
1367        int ssize = axis_domain_order.numElements();
1368        for (int i = 0; i < ssize; ++i)
1369          if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1370            ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1371                  << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1372                  << " don't have elements in the same order");
1373      }
1374    }
1375
1376    CGridGenerate gridGenerate(this, transformGridSrc);
1377    gridGenerate.completeGrid();
1378  }
1379
1380  void CGrid::transformGrid(CGrid* transformGridSrc)
1381  {
1382    if (!transformGridSrc)
1383      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1384            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1385
1386    if (isTransformed()) return;
1387    setTransformed();
1388    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1389    {
1390      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1391           << "Two grids have different dimension size"
1392           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1393           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1394    }
1395    else
1396    {
1397      int ssize = axis_domain_order.numElements();
1398      for (int i = 0; i < ssize; ++i)
1399        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1400          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1401                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1402                << " don't have elements in the same order");
1403    }
1404
1405    transformations_ = new CGridTransformation(this, transformGridSrc);
1406    transformations_->computeAll();
1407    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1408
1409    // Ok, now need to compute index of grid source
1410    transformGridSrc->checkMaskIndex(false);
1411  }
1412
1413  bool CGrid::hasTransform()
1414  {
1415    return hasTransform_;
1416  }
1417
1418  /*!
1419  \brief Get the list of domain pointers
1420  \return list of domain pointers
1421  */
1422  std::vector<CDomain*> CGrid::getDomains()
1423  {
1424    std::vector<CDomain*> domList;
1425    if (!domList_.empty())
1426    {
1427      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1428    }
1429    return domList;
1430  }
1431
1432  /*!
1433  \brief Get the list of  axis pointers
1434  \return list of axis pointers
1435  */
1436  std::vector<CAxis*> CGrid::getAxis()
1437  {
1438    std::vector<CAxis*> aList;
1439    if (!axisList_.empty())
1440      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1441
1442    return aList;
1443  }
1444
1445  /*!
1446  \brief Set domain(s) of a grid from a list
1447  \param[in] domains list of domains
1448  */
1449  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1450  {
1451    if (isDomListSet) return;
1452    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1453    if (!domains.empty() && domList.empty())
1454    {
1455      for (int i = 0; i < domains.size(); ++i)
1456        this->getVirtualDomainGroup()->addChild(domains[i]);
1457      domList = this->getVirtualDomainGroup()->getAllChildren();
1458    }
1459
1460    if (!domList.empty())
1461    {
1462      int sizeDom = domList.size();
1463      domList_.resize(sizeDom);
1464      for (int i = 0; i < sizeDom; ++i)
1465      {
1466        domList_[i] = domList[i]->getId();
1467      }
1468      isDomListSet = true;
1469    }
1470
1471  }
1472
1473  /*!
1474  \brief Set axis(s) of a grid from a list
1475  \param[in] axis list of axis
1476  */
1477  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1478  {
1479    if (isAxisListSet) return;
1480    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1481    if (!axis.empty() && aList.empty())
1482    {
1483      for (int i = 0; i < axis.size(); ++i)
1484        this->getVirtualAxisGroup()->addChild(axis[i]);
1485      aList = this->getVirtualAxisGroup()->getAllChildren();
1486    }
1487
1488    if (!aList.empty())
1489    {
1490      int sizeAxis = aList.size();
1491      axisList_.resize(sizeAxis);
1492      for (int i = 0; i < sizeAxis; ++i)
1493      {
1494        axisList_[i] = aList[i]->getId();
1495      }
1496      isAxisListSet = true;
1497    }
1498  }
1499
1500  /*!
1501  \brief Get list of id of domains
1502  \return id list of domains
1503  */
1504  std::vector<StdString> CGrid::getDomainList()
1505  {
1506    setDomainList();
1507    return domList_;
1508  }
1509
1510  /*!
1511  \brief Get list of id of axis
1512  \return id list of axis
1513  */
1514  std::vector<StdString> CGrid::getAxisList()
1515  {
1516    setAxisList();
1517    return axisList_;
1518  }
1519
1520  void CGrid::sendAllDomains()
1521  {
1522    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1523    int dSize = domList.size();
1524    for (int i = 0; i < dSize; ++i)
1525    {
1526      sendAddDomain(domList[i]->getId());
1527      domList[i]->sendAllAttributesToServer();
1528    }
1529  }
1530
1531  void CGrid::sendAllAxis()
1532  {
1533    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1534    int aSize = aList.size();
1535
1536    for (int i = 0; i < aSize; ++i)
1537    {
1538      sendAddAxis(aList[i]->getId());
1539      aList[i]->sendAllAttributesToServer();
1540    }
1541  }
1542
1543  void CGrid::parse(xml::CXMLNode& node)
1544  {
1545    SuperClass::parse(node);
1546
1547    if (node.goToChildElement())
1548    {
1549      StdString domainName("domain");
1550      StdString axisName("axis");
1551      do
1552      {
1553        if (node.getElementName() == domainName) {
1554          order_.push_back(true);
1555          this->getVirtualDomainGroup()->parseChild(node);
1556        }
1557        if (node.getElementName() == axisName) {
1558          order_.push_back(false);
1559          this->getVirtualAxisGroup()->parseChild(node);
1560        }
1561      } while (node.goToNextElement());
1562      node.goToParentElement();
1563    }
1564
1565    if (!order_.empty())
1566    {
1567      int sizeOrd = order_.size();
1568      axis_domain_order.resize(sizeOrd);
1569      for (int i = 0; i < sizeOrd; ++i)
1570      {
1571        axis_domain_order(i) = order_[i];
1572      }
1573    }
1574
1575    setDomainList();
1576    setAxisList();
1577   }
1578} // namespace xios
Note: See TracBrowser for help on using the repository browser.