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

Last change on this file since 763 was 763, checked in by rlacroix, 9 years ago

Fix: Deadlocks could occur depending on the zoom configuration.

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