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

Last change on this file since 777 was 777, checked in by mhnguyen, 8 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
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]->setAttributesReference();
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     {
221       domList[i]->setAttributesReference();
222     }
223     this->hasDomainAxisBaseRef_ = true;
224   }
225
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
232   void CGrid::checkMaskIndex(bool doSendingIndex)
233   {
234     CContext* context = CContext::getCurrent();
235     CContextClient* client=context->client;
236
237     if (isScalarGrid())
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
252     if (context->hasClient)
253      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
254
255     if (this->isChecked) return;
256
257     if (context->hasClient)
258     {
259        this->checkAttributesAfterTransformation();
260        this->checkMask();
261        this->computeIndex();
262     }
263     this->isChecked = true;
264   }
265
266   void CGrid::checkMask(void)
267   {
268      using namespace std;
269      std::vector<CDomain*> domainP = this->getDomains();
270      std::vector<CAxis*> axisP = this->getAxis();
271      int dim = domainP.size() * 2 + axisP.size();
272
273      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
274      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
275      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
276      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
277
278      switch (dim) {
279        case 1:
280          checkGridMask(mask1, domainMasks, axisMasks, axis_domain_order);
281          break;
282        case 2:
283          checkGridMask(mask2, domainMasks, axisMasks, axis_domain_order);
284          break;
285        case 3:
286          checkGridMask(mask3, domainMasks, axisMasks, axis_domain_order);
287          break;
288//        case 4:
289//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
290//          break;
291//        case 5:
292//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
293//          break;
294//        case 6:
295//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
296//          break;
297//        case 7:
298//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
299//          break;
300        default:
301          break;
302      }
303   }
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
328   //---------------------------------------------------------------
329
330   void CGrid::solveDomainRef(bool sendAtt)
331   {
332      setDomainList();
333      std::vector<CDomain*> domListP = this->getDomains();
334      if (!domListP.empty())
335      {
336        for (int i = 0; i < domListP.size(); ++i)
337        {
338          if (sendAtt) domListP[i]->sendCheckedAttributes();
339          else domListP[i]->checkAttributesOnClient();
340        }
341      }
342   }
343
344   //---------------------------------------------------------------
345
346   void CGrid::solveAxisRef(bool sendAtt)
347   {
348      setAxisList();
349      std::vector<CAxis*> axisListP = this->getAxis();
350      if (!axisListP.empty())
351      {
352        int idx = 0;
353        axisPositionInGrid_.resize(0);
354        for (int i = 0; i < axis_domain_order.numElements(); ++i)
355        {
356          if (false == axis_domain_order(i))
357          {
358            axisPositionInGrid_.push_back(idx);
359            ++idx;
360          }
361          else idx += 2;
362        }
363
364        for (int i = 0; i < axisListP.size(); ++i)
365        {
366          if (sendAtt)
367            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
368          else
369            axisListP[i]->checkAttributesOnClient();
370          ++idx;
371        }
372      }
373   }
374
375   std::vector<int> CGrid::getAxisPositionInGrid() const
376   {
377     return axisPositionInGrid_;
378   }
379
380   //---------------------------------------------------------------
381
382   void CGrid::computeIndex(void)
383   {
384     CContext* context = CContext::getCurrent();
385     CContextClient* client = context->client;
386
387     // First of all, compute distribution on client side
388     clientDistribution_ = new CDistributionClient(client->clientRank, this);
389     // Get local data index on client
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];
393     isDataDistributed_= clientDistribution_->isDataDistributed();
394
395     if (!doGridHaveDataDistributed())
396     {
397        if (0 == client->clientRank)
398        {
399          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
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
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;
419
420     // Then compute distribution on server side
421     CServerDistributionDescription serverDistributionDescription(globalDim_);
422     serverDistributionDescription.computeServerGlobalIndexInRange(client->serverSize,
423                                                                   std::make_pair<size_t,size_t>(indexBegin, indexEnd),
424                                                                   positionDimensionDistributed_);
425
426     // Finally, compute index mapping between client(s) and server(s)
427     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription.getGlobalIndexRange(),
428                                                            client->intraComm,
429                                                            clientDistribution_->isDataDistributed());
430
431     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex());
432     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
433
434     const std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
435     std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
436     itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
437     iteGlobalMap = globalIndexOnServer.end();
438
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);
448       XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
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     }
461
462     connectedServerRank_.clear();
463     for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
464       connectedServerRank_.push_back(it->first);
465     }
466
467     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
468   }
469
470   //----------------------------------------------------------------
471
472   CGrid* CGrid::createGrid(CDomain* domain)
473   {
474      std::vector<CDomain*> vecDom(1, domain);
475      std::vector<CAxis*> vecAxis;
476
477      return createGrid(vecDom, vecAxis);
478   }
479
480   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
481   {
482      std::vector<CDomain*> vecDom(1, domain);
483      std::vector<CAxis*> vecAxis(1, axis);
484
485      return createGrid(vecDom, vecAxis);
486   }
487
488   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
489                            const CArray<bool,1>& axisDomainOrder)
490   {
491      return createGrid(generateId(domains, axis, axisDomainOrder), domains, axis, axisDomainOrder);
492   }
493
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);
503      grid->setDomainList(domains);
504      grid->setAxisList(axis);
505
506      // By default, domains are always the first elements of a grid
507      if (0 == axisDomainOrder.numElements())
508      {
509        int size = domains.size() + axis.size();
510        grid->axis_domain_order.resize(size);
511        for (int i = 0; i < size; ++i)
512        {
513          if (i < domains.size()) grid->axis_domain_order(i) = true;
514          else grid->axis_domain_order(i) = false;
515        }
516      }
517      else
518      {
519        grid->axis_domain_order.resize(axisDomainOrder.numElements());
520        grid->axis_domain_order = axisDomainOrder;
521      }
522
523      grid->solveDomainAxisRefInheritance(true);
524
525      return grid;
526   }
527
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
569   CDomainGroup* CGrid::getVirtualDomainGroup() const
570   {
571     return this->vDomainGroup_;
572   }
573
574   CAxisGroup* CGrid::getVirtualAxisGroup() const
575   {
576     return this->vAxisGroup_;
577   }
578
579   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
580   {
581     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
582     StdSize numElements = stored.numElements();
583     for (StdSize n = 0; n < numElements; ++n)
584     {
585       field[out_i(n)] = stored(n);
586     }
587   }
588
589   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
590   {
591     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
592     StdSize numElements = stored.numElements();
593     for (StdSize n = 0; n < numElements; ++n)
594     {
595       stored(n) = field[out_i(n)];
596     }
597   }
598
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
609   //----------------------------------------------------------------
610
611   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
612   {
613      const StdSize size = storeIndex_client.numElements();
614
615      stored.resize(size);
616      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
617   }
618
619   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
620   {
621      const StdSize size = storeIndex_client.numElements();
622
623      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
624   }
625
626  void CGrid::computeIndexScalarGrid()
627  {
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
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
675  void CGrid::sendIndexScalarGrid()
676  {
677    CContext* context = CContext::getCurrent();
678    CContextClient* client = context->client;
679
680    CEventClient event(getType(), EVENT_ID_INDEX);
681    list<CMessage> listMsg;
682    list<CArray<size_t,1> > listOutIndex;
683
684    if (0 == client->clientRank)
685    {
686      for (int rank = 0; rank < client->serverSize; ++rank)
687      {
688        int nb = 1;
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
695        for (int k = 0; k < nb; ++k)
696        {
697          outGlobalIndexOnServer(k) = 0;
698          outLocalIndexToServer(k)  = 0;
699        }
700
701        listMsg.push_back(CMessage());
702        listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
703
704        event.push(rank, 1, listMsg.back());
705      }
706
707      client->sendEvent(event);
708    }
709    else
710      client->sendEvent(event);
711  }
712
713  void CGrid::sendIndex(void)
714  {
715    CContext* context = CContext::getCurrent();
716    CContextClient* client = context->client;
717
718    CEventClient event(getType(), EVENT_ID_INDEX);
719    int rank;
720    list<CMessage> listMsg;
721    list<CArray<size_t,1> > listOutIndex;
722    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
723    const std::vector<int>& localIndexSendToServer = clientDistribution_->getLocalDataIndexSendToServer();
724    const std::vector<size_t>& globalIndexSendToServer = clientDistribution_->getGlobalDataIndexSendToServer();
725
726    if (!doGridHaveDataDistributed())
727    {
728      if (0 == client->clientRank)
729      {
730        CArray<size_t,1> outGlobalIndexOnServer(globalIndexSendToServer.size());
731        for (int idx = 0; idx < globalIndexSendToServer.size();++idx)
732          outGlobalIndexOnServer(idx) = globalIndexSendToServer[idx];
733
734        CArray<int,1> outLocalIndexToServer(localIndexSendToServer.size());
735        for (int idx = 0; idx < localIndexSendToServer.size();++idx)
736          outLocalIndexToServer(idx) = localIndexSendToServer[idx];
737
738        for (rank = 0; rank < client->serverSize; ++rank)
739        {
740          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
741          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
742
743          listMsg.push_back(CMessage());
744          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
745
746          event.push(rank, 1, listMsg.back());
747        }
748
749        client->sendEvent(event);
750      }
751      else
752        client->sendEvent(event);
753    }
754    else
755    {
756      std::map<int, std::vector<size_t> >::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
757      itbGlobalMap = itGlobalMap = globalIndexOnServer.begin();
758      iteGlobalMap = globalIndexOnServer.end();
759
760      int nbGlobalIndex = globalIndexSendToServer.size();
761      std::map<int,std::vector<int> >localIndexTmp;
762      std::map<int,std::vector<size_t> > globalIndexTmp;
763
764      typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
765      std::vector<int>::iterator itVec;
766      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
767      {
768        int serverRank = itGlobalMap->first;
769        int indexSize = itGlobalMap->second.size();
770        std::vector<int> permutIndex(indexSize);
771        XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
772        XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(itGlobalMap->second, permutIndex);
773        BinarySearch binSearch(itGlobalMap->second);
774
775        for (int i = 0; i < nbGlobalIndex; ++i)
776        {
777          if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexSendToServer[i], itVec))
778          {
779            globalIndexTmp[serverRank].push_back(globalIndexSendToServer[i]);
780            localIndexTmp[serverRank].push_back(localIndexSendToServer[i]);
781          }
782        }
783      }
784
785      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
786      {
787        rank = connectedServerRank_[ns];
788        int nb = 0;
789        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
790          nb = globalIndexTmp[rank].size();
791
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
798        for (int k = 0; k < nb; ++k)
799        {
800          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
801          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
802        }
803
804        listMsg.push_back(CMessage());
805        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
806
807        event.push(rank, nbSenders[rank], listMsg.back());
808      }
809
810      client->sendEvent(event);
811    }
812  }
813
814  void CGrid::recvIndex(CEventServer& event)
815  {
816    string gridId;
817    vector<int> ranks;
818    vector<CBufferIn*> buffers;
819
820    list<CEventServer::SSubEvent>::iterator it;
821    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
822    {
823      ranks.push_back(it->rank);
824      CBufferIn* buffer = it->buffer;
825      *buffer >> gridId;
826      buffers.push_back(buffer);
827    }
828    get(gridId)->recvIndex(ranks, buffers);
829  }
830
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      {
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
850        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
851        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
852
853        ++idxDomain;
854        idx += 2;
855      }
856      else
857      {
858        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
859        ++idxAxis;
860        ++idx;
861      }
862    }
863  }
864
865  std::vector<int> CGrid::getGlobalDimension()
866  {
867    return globalDim_;
868  }
869
870  bool CGrid::isScalarGrid() const
871  {
872    return (axisList_.empty() && domList_.empty());
873  }
874
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
878    just only want to zoom on a domain.
879  */
880  bool CGrid::doGridHaveDataToWrite()
881  {
882     return (0 != writtenDataSize_);
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
888    an one dimension array.
889    \return size of data written on server
890  */
891  size_t CGrid::getWrittenDataSize() const
892  {
893    return writtenDataSize_;
894  }
895
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
923  const CDistributionServer* CGrid::getDistributionServer() const
924  {
925    return serverDistribution_;
926  }
927
928  const CDistributionClient* CGrid::getDistributionClient() const
929  {
930    return clientDistribution_;
931  }
932
933  bool CGrid::doGridHaveDataDistributed()
934  {
935    if (isScalarGrid()) return false;
936    else
937      return isDataDistributed_;
938  }
939
940  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
941  {
942    CContext* context = CContext::getCurrent();
943    CContextServer* server = context->server;
944    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
945
946    for (int n = 0; n < ranks.size(); n++)
947    {
948      int rank = ranks[n];
949      CBufferIn& buffer = *buffers[n];
950
951      buffer >> isDataDistributed_ >> isCompressible_;
952      size_t dataSize = 0;
953
954      if (isScalarGrid())
955      {
956        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
957        CArray<size_t,1> outIndex;
958        buffer >> outIndex;
959        outIndexFromClient.insert(std::make_pair(rank, outIndex));
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          {
976            ++ssize;
977            idx += 2;
978          }
979          else
980            ++idx;
981        }
982
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;
993            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
994            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
995
996            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
997            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
998            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
999            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1000            ++domainId;
1001          }
1002          else
1003          {
1004            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1005            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1006            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
1007            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1008            ++axisId;
1009          }
1010        }
1011        dataSize = 1;
1012        for (int i = 0; i < nZoomSize.size(); ++i)
1013          dataSize *= nZoomSize[i];
1014
1015        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1016                                                      nZoomBeginGlobal, nGlob);
1017      }
1018
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;
1029
1030      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1031      connectedDataSize_[rank] = outIndex.numElements();
1032      numberWrittenIndexes_ += outIndex.numElements();
1033    }
1034
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
1044    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1045  }
1046
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   */
1054  bool CGrid::dispatchEvent(CEventServer& event)
1055  {
1056
1057    if (SuperClass::dispatchEvent(event)) return true;
1058    else
1059    {
1060      switch(event.type)
1061      {
1062        case EVENT_ID_INDEX :
1063          recvIndex(event);
1064          return true;
1065          break;
1066
1067         case EVENT_ID_ADD_DOMAIN :
1068           recvAddDomain(event);
1069           return true;
1070           break;
1071
1072         case EVENT_ID_ADD_AXIS :
1073           recvAddAxis(event);
1074           return true;
1075           break;
1076        default :
1077          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1078                << "Unknown Event");
1079          return false;
1080      }
1081    }
1082  }
1083
1084   ///---------------------------------------------------------------
1085
1086   CDomain* CGrid::addDomain(const std::string& id)
1087   {
1088     return vDomainGroup_->createChild(id);
1089   }
1090
1091   CAxis* CGrid::addAxis(const std::string& id)
1092   {
1093     return vAxisGroup_->createChild(id);
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   {
1127    CContext* context=CContext::getCurrent();
1128
1129    if (! context->hasServer )
1130    {
1131       CContextClient* client=context->client;
1132
1133       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1134       if (client->isServerLeader())
1135       {
1136         CMessage msg;
1137         msg<<this->getId();
1138         msg<<id;
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);
1142         client->sendEvent(event);
1143       }
1144       else client->sendEvent(event);
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   {
1154    CContext* context=CContext::getCurrent();
1155
1156    if (! context->hasServer )
1157    {
1158       CContextClient* client=context->client;
1159
1160       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1161       if (client->isServerLeader())
1162       {
1163         CMessage msg;
1164         msg<<this->getId();
1165         msg<<id;
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);
1169         client->sendEvent(event);
1170       }
1171       else client->sendEvent(event);
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
1182      CBufferIn* buffer = event.subEvents.begin()->buffer;
1183      string id;
1184      *buffer >> id;
1185      get(id)->recvAddDomain(*buffer);
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   {
1194      string id;
1195      buffer >> id;
1196      addDomain(id);
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
1206      CBufferIn* buffer = event.subEvents.begin()->buffer;
1207      string id;
1208      *buffer >> id;
1209      get(id)->recvAddAxis(*buffer);
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   {
1218      string id;
1219      buffer >> id;
1220      addAxis(id);
1221   }
1222
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  */
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);
1242        pDom->solveSrcInheritance();
1243        pDom->solveInheritanceTransformation();
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);
1255        pAxis->solveInheritanceTransformation();
1256      }
1257    }
1258  }
1259
1260  bool CGrid::isTransformed()
1261  {
1262    return isTransformed_;
1263  }
1264
1265  void CGrid::setTransformed()
1266  {
1267    isTransformed_ = true;
1268  }
1269
1270  CGridTransformation* CGrid::getTransformations()
1271  {
1272    return transformations_;
1273  }
1274
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  {
1281    if (0 != transformGridSrc)
1282    {
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      }
1299    }
1300
1301    CGridGenerate gridGenerate(this, transformGridSrc);
1302    gridGenerate.completeGrid();
1303  }
1304
1305  void CGrid::transformGrid(CGrid* transformGridSrc)
1306  {
1307    if (!transformGridSrc)
1308      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1309            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1310
1311    if (isTransformed()) return;
1312    setTransformed();
1313    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1314    {
1315      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1316           << "Two grids have different dimension size"
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());
1319    }
1320    else
1321    {
1322      int ssize = axis_domain_order.numElements();
1323      for (int i = 0; i < ssize; ++i)
1324        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1325          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1326                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1327                << " don't have elements in the same order");
1328    }
1329
1330    transformations_ = new CGridTransformation(this, transformGridSrc);
1331    transformations_->computeAll();
1332
1333    // Ok, now need to compute index of grid source
1334    transformGridSrc->checkMaskIndex(false);
1335  }
1336
1337  /*!
1338  \brief Get the list of domain pointers
1339  \return list of domain pointers
1340  */
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
1351  /*!
1352  \brief Get the list of  axis pointers
1353  \return list of axis pointers
1354  */
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
1364  /*!
1365  \brief Set domain(s) of a grid from a list
1366  \param[in] domains list of domains
1367  */
1368  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1369  {
1370    if (isDomListSet) return;
1371    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
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
1379    if (!domList.empty())
1380    {
1381      int sizeDom = domList.size();
1382      domList_.resize(sizeDom);
1383      for (int i = 0; i < sizeDom; ++i)
1384      {
1385        domList_[i] = domList[i]->getId();
1386      }
1387      isDomListSet = true;
1388    }
1389
1390  }
1391
1392  /*!
1393  \brief Set axis(s) of a grid from a list
1394  \param[in] axis list of axis
1395  */
1396  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1397  {
1398    if (isAxisListSet) return;
1399    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
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
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
1419  /*!
1420  \brief Get list of id of domains
1421  \return id list of domains
1422  */
1423  std::vector<StdString> CGrid::getDomainList()
1424  {
1425    setDomainList();
1426    return domList_;
1427  }
1428
1429  /*!
1430  \brief Get list of id of axis
1431  \return id list of axis
1432  */
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
1462  void CGrid::parse(xml::CXMLNode& node)
1463  {
1464    SuperClass::parse(node);
1465
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;
1468
1469    if (node.goToChildElement())
1470    {
1471      StdString domainName("domain");
1472      StdString axisName("axis");
1473      do
1474      {
1475        if (node.getElementName() == domainName) {
1476          order.push_back(true);
1477          this->getVirtualDomainGroup()->parseChild(node);
1478        }
1479        if (node.getElementName() == axisName) {
1480          order.push_back(false);
1481          this->getVirtualAxisGroup()->parseChild(node);
1482        }
1483      } while (node.goToNextElement());
1484      node.goToParentElement();
1485    }
1486
1487    if (!order.empty())
1488    {
1489      int sizeOrd = order.size();
1490      axis_domain_order.resize(sizeOrd);
1491      for (int i = 0; i < sizeOrd; ++i)
1492      {
1493        axis_domain_order(i) = order[i];
1494      }
1495    }
1496
1497    setDomainList();
1498    setAxisList();
1499   }
1500} // namespace xios
Note: See TracBrowser for help on using the repository browser.