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

Last change on this file since 775 was 775, checked in by mhnguyen, 6 years ago

Implementing the reading of attributes of an axis from a file

+) 3d grid can be read directly from a file
+) Clean some redundant codes
+) Add new attribute declaration that allows to output only desired attributes

Test
+) On Curie
+) test_remap passes and result is correct

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