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

Last change on this file since 785 was 777, checked in by mhnguyen, 9 years ago

Fixing some minors bug during merge

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