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

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

Adding a new transformation: Reduce a domain to an axis

Test
+) On Curie
+) Tests pass and are correct

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 62.9 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_(), domList_(), isDomListSet(false)
29      , vAxisGroup_(), axisList_(), isAxisListSet(false)
30      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
31      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
32      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
33      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
34      , transformations_(0), isTransformed_(false)
35      , axisPositionInGrid_(), positionDimensionDistributed_(1), hasDomainAxisBaseRef_(false)
36      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
37   {
38     setVirtualDomainGroup();
39     setVirtualAxisGroup();
40     setVirtualScalarGroup();
41   }
42
43   CGrid::CGrid(const StdString& id)
44      : CObjectTemplate<CGrid>(id), CGridAttributes()
45      , isChecked(false), isDomainAxisChecked(false)
46      , vDomainGroup_(), domList_(), isDomListSet(false)
47      , vAxisGroup_(), axisList_(), isAxisListSet(false)
48      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
49      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
50      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
51      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
52      , transformations_(0), isTransformed_(false)
53      , axisPositionInGrid_(), positionDimensionDistributed_(1), hasDomainAxisBaseRef_(false)
54      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
55   {
56     setVirtualDomainGroup();
57     setVirtualAxisGroup();
58     setVirtualScalarGroup();
59   }
60
61   CGrid::~CGrid(void)
62   {
63    if (0 != clientDistribution_) delete clientDistribution_;
64    if (0 != serverDistribution_) delete serverDistribution_;
65    if (0 != clientServerMap_) delete clientServerMap_;
66    if (0 != transformations_) delete transformations_;
67   }
68
69   ///---------------------------------------------------------------
70
71   StdString CGrid::GetName(void)    { return StdString("grid"); }
72   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
73   ENodeType CGrid::GetType(void)    { return eGrid; }
74
75
76   StdSize CGrid::getDimension(void) const
77   {
78      return globalDim_.size();
79   }
80
81   //---------------------------------------------------------------
82
83   StdSize CGrid::getDataSize(void) const
84   {
85     StdSize retvalue = 1;
86     if (!isScalarGrid())
87     {
88       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
89       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];
90     }
91     return retvalue;
92   }
93
94   /*!
95    * Compute the minimum buffer size required to send the attributes to the server(s).
96    *
97    * \return A map associating the server rank with its minimum buffer size.
98    */
99   std::map<int, StdSize> CGrid::getAttributesBufferSize()
100   {
101     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
102
103     // The grid indexes require a similar size as the actual data
104     std::map<int, StdSize> dataSizes = getDataBufferSize();
105     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
106     for (it = dataSizes.begin(); it != itE; ++it)
107     {
108       it->second += 2 * sizeof(bool);
109       if (it->second > attributesSizes[it->first])
110         attributesSizes[it->first] = it->second;
111     }
112
113     // Account for the axis attributes
114     std::vector<CAxis*> axisList = getAxis();
115     for (size_t i = 0; i < axisList.size(); ++i)
116     {
117       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize();
118       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
119       {
120         if (it->second > attributesSizes[it->first])
121           attributesSizes[it->first] = it->second;
122       }
123     }
124
125     // Account for the domain attributes
126     std::vector<CDomain*> domList = getDomains();
127     for (size_t i = 0; i < domList.size(); ++i)
128     {
129       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize();
130       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
131       {
132         if (it->second > attributesSizes[it->first])
133           attributesSizes[it->first] = it->second;
134       }
135     }
136
137     return attributesSizes;
138   }
139
140   /*!
141    * Compute the minimum buffer size required to send the data to the server(s).
142    *
143    * \param id the id used to tag the data
144    * \return A map associating the server rank with its minimum buffer size.
145    */
146   std::map<int, StdSize> CGrid::getDataBufferSize(const std::string& id /*= ""*/)
147   {
148     std::map<int, StdSize> dataSizes;
149     // The record index is sometimes sent along with the data but we always
150     // include it in the size calculation for the sake of simplicity
151     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() + 2 * sizeof(size_t);
152
153     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_.end();
154     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
155     {
156       int rank = connectedServerRank_[k];
157       std::map<int, size_t>::const_iterator it = connectedDataSize_.find(rank);
158       size_t count = (it != itEnd) ? it->second : 0;
159
160       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
161     }
162
163     return dataSizes;
164   }
165
166   void CGrid::checkAttributesAfterTransformation()
167   {
168     setDomainList();
169     std::vector<CDomain*> domListP = this->getDomains();
170     if (!domListP.empty())
171     {
172       for (int i = 0; i < domListP.size(); ++i)
173       {
174         domListP[i]->checkAttributesOnClientAfterTransformation();
175       }
176     }
177   }
178
179   //---------------------------------------------------------------
180
181   /*!
182    * Test whether the data defined on the grid can be outputted in a compressed way.
183    *
184    * \return true if and only if a mask was defined for this grid
185    */
186   bool CGrid::isCompressible(void) const
187   {
188      return isCompressible_;
189   }
190
191   //---------------------------------------------------------------
192
193   void CGrid::addRelFileCompressed(const StdString& filename)
194   {
195      this->relFilesCompressed.insert(filename);
196   }
197
198   bool CGrid::isWrittenCompressed(const StdString& filename) const
199   {
200      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
201   }
202
203   //---------------------------------------------------------------
204
205   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
206   {
207     if (this->isDomainAxisChecked) return;
208
209     this->solveScalarRef(areAttributesChecked);
210     this->solveAxisRef(areAttributesChecked);
211     this->solveDomainRef(areAttributesChecked);
212     computeGridGlobalDimension(getDomains(), getAxis(), getScalars(), axis_domain_order);
213     this->isDomainAxisChecked = areAttributesChecked;
214   }
215
216   void CGrid::solveDomainAxisBaseRef()
217   {
218     if (this->hasDomainAxisBaseRef_) return;
219     // Account for the scalar attributes
220     std::vector<CScalar*> scalarList = getScalars();
221     for (size_t i = 0; i < scalarList.size(); ++i)
222     {
223       scalarList[i]->setAttributesReference();
224     }
225
226     // Account for the axis attributes
227     std::vector<CAxis*> axisList = getAxis();
228     for (size_t i = 0; i < axisList.size(); ++i)
229     {
230       axisList[i]->setAttributesReference();
231     }
232
233     // Account for the domain attributes
234     std::vector<CDomain*> domList = getDomains();
235     for (size_t i = 0; i < domList.size(); ++i)
236     {
237       domList[i]->setAttributesReference();
238     }
239
240     this->hasDomainAxisBaseRef_ = true;
241   }
242
243   void CGrid::checkEligibilityForCompressedOutput()
244   {
245     // We don't check if the mask is valid here, just if a mask has been defined at this point.
246     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
247   }
248
249   void CGrid::checkMaskIndex(bool doSendingIndex)
250   {
251     CContext* context = CContext::getCurrent();
252     CContextClient* client=context->client;
253
254     if (isScalarGrid())
255     {
256       if (context->hasClient)
257          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
258
259       if (this->isChecked) return;
260       if (context->hasClient)
261       {
262          this->computeIndexScalarGrid();
263       }
264
265       this->isChecked = true;
266       return;
267     }
268
269     if (context->hasClient)
270      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
271
272     if (this->isChecked) return;
273
274     if (context->hasClient)
275     {
276        this->checkAttributesAfterTransformation();
277        this->checkMask();
278        this->computeIndex();
279     }
280     this->isChecked = true;
281   }
282
283   void CGrid::createMask(void)
284   {
285      using namespace std;
286      std::vector<CDomain*> domainP = this->getDomains();
287      std::vector<CAxis*> axisP = this->getAxis();
288      int dim = domainP.size() * 2 + axisP.size();
289
290      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
291      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
292      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
293      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
294
295      switch (dim) {
296        case 1:
297          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
298          break;
299        case 2:
300          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
301          break;
302        case 3:
303          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
304          break;
305        default:
306          break;
307      }
308   }
309
310   void CGrid::checkMask(void)
311   {
312      using namespace std;
313      std::vector<CDomain*> domainP = this->getDomains();
314      std::vector<CAxis*> axisP = this->getAxis();
315      int dim = domainP.size() * 2 + axisP.size();
316
317      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
318      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
319      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
320      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
321
322      switch (dim) {
323        case 1:
324          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
325          break;
326        case 2:
327          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
328          break;
329        case 3:
330          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
331          break;
332//        case 4:
333//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
334//          break;
335//        case 5:
336//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
337//          break;
338//        case 6:
339//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
340//          break;
341//        case 7:
342//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
343//          break;
344        default:
345          break;
346      }
347   }
348
349   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
350   {
351      using namespace std;
352      std::vector<CDomain*> domainP = this->getDomains();
353      std::vector<CAxis*> axisP = this->getAxis();
354      int dim = domainP.size() * 2 + axisP.size();
355
356      switch (dim) {
357        case 1:
358          modifyGridMask(mask_1d, indexToModify);
359          break;
360        case 2:
361          modifyGridMask(mask_2d, indexToModify);
362          break;
363        case 3:
364          modifyGridMask(mask_3d, indexToModify);
365          break;
366
367        default:
368          break;
369      }
370   }
371
372   //---------------------------------------------------------------
373
374   void CGrid::solveDomainRef(bool sendAtt)
375   {
376      setDomainList();
377      std::vector<CDomain*> domListP = this->getDomains();
378      if (!domListP.empty())
379      {
380        for (int i = 0; i < domListP.size(); ++i)
381        {
382          if (sendAtt) domListP[i]->sendCheckedAttributes();
383          else domListP[i]->checkAttributesOnClient();
384        }
385      }
386   }
387
388   //---------------------------------------------------------------
389
390   void CGrid::solveAxisRef(bool sendAtt)
391   {
392      setAxisList();
393      std::vector<CAxis*> axisListP = this->getAxis();
394      if (!axisListP.empty())
395      {
396        int idx = 0;
397        axisPositionInGrid_.resize(0);
398        for (int i = 0; i < axis_domain_order.numElements(); ++i)
399        {
400          int elementDimension = axis_domain_order(i);
401          if (1 == elementDimension)
402          {
403            axisPositionInGrid_.push_back(idx);
404            ++idx;
405          }
406          else if (2 == elementDimension) idx += 2;
407        }
408
409        for (int i = 0; i < axisListP.size(); ++i)
410        {
411          if (sendAtt)
412            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
413          else
414            axisListP[i]->checkAttributesOnClient();
415        }
416      }
417   }
418
419   //---------------------------------------------------------------
420
421   void CGrid::solveScalarRef(bool sendAtt)
422   {
423      setScalarList();
424      std::vector<CScalar*> scalarListP = this->getScalars();
425      if (!scalarListP.empty())
426      {
427        for (int i = 0; i < scalarListP.size(); ++i)
428        {
429          /*Nothing to do for now */
430//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
431//          else scalarListP[i]->checkAttributesOnClient();
432        }
433      }
434   }
435
436   std::vector<int> CGrid::getAxisPositionInGrid() const
437   {
438     return axisPositionInGrid_;
439   }
440
441   //---------------------------------------------------------------
442
443   /*!
444     Compute the global index of grid to send to server as well as the connected server of the current client.
445     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
446     their global index. We can have a map of global index of grid and local index that each client holds
447     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
448     of the current client.
449   */
450   void CGrid::computeIndex(void)
451   {
452     CContext* context = CContext::getCurrent();
453     CContextClient* client = context->client;
454
455     // First of all, compute distribution on client side
456     clientDistribution_ = new CDistributionClient(client->clientRank, this);
457     // Get local data index on client
458     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
459     int nbStoreIndex = storeIndex_client.numElements();
460     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
461     isDataDistributed_= clientDistribution_->isDataDistributed();
462
463     if (!doGridHaveDataDistributed())
464     {
465        if (0 == client->clientRank)
466        {
467          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
468          for (int rank = 0; rank < client->serverSize; ++rank)
469            connectedDataSize_[rank] = ssize;
470        }
471        return;
472     }
473
474     // Compute mapping between client and server
475     std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
476     CServerDistributionDescription serverDistributionDescription(globalDim_, client->serverSize);
477     serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
478                                                                client->clientRank,
479                                                                client->clientSize,
480                                                                axis_domain_order,
481                                                                positionDimensionDistributed_);
482     computeIndexByElement(indexServerOnElement, globalIndexOnServer_);
483
484     const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
485     CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
486     CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
487     itGlobalMap  = itbGlobalMap = globalIndexOnServer_.begin();
488     iteGlobalMap = globalIndexOnServer_.end();
489
490     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
491     {
492       int serverRank = itGlobalMap->first;
493       int indexSize = itGlobalMap->second.size();
494       const std::vector<size_t>& indexVec = itGlobalMap->second;
495       for (int idx = 0; idx < indexSize; ++idx)
496       {
497          itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
498          if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
499          {
500             if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
501               connectedDataSize_[serverRank] = 1;
502             else
503               ++connectedDataSize_[serverRank];
504          }
505       }
506     }
507
508     connectedServerRank_.clear();
509     for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
510       connectedServerRank_.push_back(itGlobalMap->first);
511     }
512
513     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
514   }
515
516   /*!
517      Compute the global of (client) grid to send to server with the global index of each element of grid
518      Each element of grid has its own global index associated to a groups of server. We only search for the global index of each element whose
519      server is the same, then calculate the global index of grid. This way can reduce so much the time for executing DHT, which only needs to run
520      on each element whose size is much smaller than one of whole grid.
521      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
522      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
523   */
524   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
525                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
526   {
527     CContext* context = CContext::getCurrent();
528     CContextClient* client = context->client;
529     int serverSize = client->serverSize;
530     std::vector<CDomain*> domList = getDomains();
531     std::vector<CAxis*> axisList = getAxis();
532
533     // Some pre-calculations of global index on each element of current grid.
534     int nbElement = axis_domain_order.numElements();
535     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
536     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
537     std::vector<size_t> elementNGlobal(nbElement);
538     elementNGlobal[0] = 1;
539     size_t globalSize = 1;
540     for (int idx = 0; idx < nbElement; ++idx)
541     {
542       elementNGlobal[idx] = globalSize;
543       size_t elementSize;
544       size_t elementGlobalSize = 1;
545       if (2 == axis_domain_order(idx))
546       {
547         elementSize = domList[domainIdx]->i_index.numElements();
548         globalIndexElement[idx].resize(elementSize);
549         for (int jdx = 0; jdx < elementSize; ++jdx)
550         {
551           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
552         }
553         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
554         ++domainIdx;
555       }
556       else if (1 == axis_domain_order(idx))
557       {
558         elementSize = axisList[axisIdx]->index.numElements();
559         globalIndexElement[idx].resize(elementSize);
560         for (int jdx = 0; jdx < elementSize; ++jdx)
561         {
562           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
563         }
564         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
565         ++axisIdx;
566       }
567       else
568       {
569         globalIndexElement[idx].resize(1);
570         globalIndexElement[idx](0) = 0;
571         elementGlobalSize = 1;
572       }
573       globalSize *= elementGlobalSize;
574     }
575
576     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
577     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
578     for (int idx = 0; idx < nbElement; ++idx)
579     {
580       std::vector<int> nbIndexOnServer(serverSize,0);
581       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
582       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
583       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
584       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
585       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
586       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
587                                                                    ite = globalIndexElementOnServerMap.end(), it;
588       for (it = itb; it != ite; ++it)
589       {
590         const std::vector<int>& tmp = it->second;
591         for (int i = 0; i < tmp.size(); ++i)
592         {
593           ++nbIndexOnServer[tmp[i]];
594         }
595       }
596
597       for (int i = 0; i < serverSize; ++i)
598       {
599         if (0 != nbIndexOnServer[i])
600         {
601           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer[i]);
602           nbIndexOnServer[i] = 0;
603           elementOnServer[idx][i] = true;
604         }
605       }
606
607       for (it = itb; it != ite; ++it)
608       {
609         const std::vector<int>& tmp = it->second;
610         for (int i = 0; i < tmp.size(); ++i)
611         {
612           globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer[tmp[i]]] = it->first;
613           ++nbIndexOnServer[tmp[i]];
614         }
615       }
616     }
617
618    // Determine server which contain global source index
619    std::vector<bool> intersectedProc(serverSize, true);
620    for (int idx = 0; idx < nbElement; ++idx)
621    {
622      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
623                     intersectedProc.begin(), intersectedProc.begin(),
624                     std::logical_and<bool>());
625    }
626
627    std::vector<int> srcRank;
628    for (int idx = 0; idx < serverSize; ++idx)
629    {
630      if (intersectedProc[idx]) srcRank.push_back(idx);
631    }
632
633    // Compute the global index of grid from global index of each element.
634    for (int i = 0; i < srcRank.size(); ++i)
635    {
636      size_t ssize = 1;
637      int rankSrc = srcRank[i];
638      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
639      std::vector<size_t> currentIndex(nbElement,0);
640      for (int idx = 0; idx < nbElement; ++idx)
641      {
642        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
643        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
644      }
645      globalIndexOnServer[rankSrc].resize(ssize);
646
647      std::vector<int> idxLoop(nbElement,0);
648      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
649      size_t idx = 0;
650      while (idx < ssize)
651      {
652        for (int ind = 0; ind < nbElement; ++ind)
653        {
654          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
655          {
656            idxLoop[ind] = 0;
657            ++idxLoop[ind+1];
658          }
659
660          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
661        }
662
663        for (int ind = 0; ind < innnerLoopSize; ++ind)
664        {
665          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
666          size_t globalSrcIndex = 0;
667          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
668          {
669            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
670          }
671          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
672          ++idx;
673          ++idxLoop[0];
674        }
675      }
676    }
677   }
678   //----------------------------------------------------------------
679
680   CGrid* CGrid::createGrid(CDomain* domain)
681   {
682      std::vector<CDomain*> vecDom(1, domain);
683      std::vector<CAxis*> vecAxis;
684
685      return createGrid(vecDom, vecAxis);
686   }
687
688   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
689   {
690      std::vector<CDomain*> vecDom(1, domain);
691      std::vector<CAxis*> vecAxis(1, axis);
692
693      return createGrid(vecDom, vecAxis);
694   }
695
696   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
697                            const CArray<int,1>& axisDomainOrder)
698   {
699     std::vector<CScalar*> vecScalar;
700     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
701   }
702
703   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
704                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
705   {
706     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
707   }
708
709   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
710                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
711   {
712      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
713        ERROR("CGrid* CGrid::createGrid(...)",
714              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
715              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
716
717      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
718      grid->setDomainList(domains);
719      grid->setAxisList(axis);
720      grid->setScalarList(scalars);
721
722      // By default, domains are always the first elements of a grid
723      if (0 == axisDomainOrder.numElements())
724      {
725        int size = domains.size() + axis.size() + scalars.size();
726        int nb = 0;
727        grid->axis_domain_order.resize(size);
728        for (int i = 0; i < size; ++i)
729        {
730          if (i < domains.size()) {
731            grid->axis_domain_order(i) = 2;
732
733          }
734          else if ((scalars.size() < (size-nb)) < size) {
735            grid->axis_domain_order(i) = 1;
736          }
737          else
738            grid->axis_domain_order(i) = 0;
739          ++nb;
740        }
741      }
742      else
743      {
744        grid->axis_domain_order.resize(axisDomainOrder.numElements());
745        grid->axis_domain_order = axisDomainOrder;
746      }
747
748      grid->solveDomainAxisRefInheritance(true);
749
750      return grid;
751   }
752
753   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
754   {
755     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
756     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
757     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
758
759     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
760     {
761       CDomain* domain = CDomain::createDomain();
762       domain->duplicateAttributes(domainSrcTmp[idx]);
763       domain->duplicateTransformation(domainSrcTmp[idx]);
764       domain->solveRefInheritance(true);
765       domain->solveInheritanceTransformation();
766       domainSrc.push_back(domain);
767     }
768
769     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
770     {
771       CAxis* axis = CAxis::createAxis();
772       axis->duplicateAttributes(axisSrcTmp[idx]);
773       axis->duplicateTransformation(axisSrcTmp[idx]);
774       axis->solveRefInheritance(true);
775       axis->solveInheritanceTransformation();
776       axisSrc.push_back(axis);
777     }
778
779     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
780     {
781       CScalar* scalar = CScalar::createScalar();
782       scalar->duplicateAttributes(scalarSrcTmp[idx]);
783       scalar->duplicateTransformation(scalarSrcTmp[idx]);
784       scalar->solveRefInheritance(true);
785       scalar->solveInheritanceTransformation();
786       scalarSrc.push_back(scalar);
787     }
788
789      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
790
791      return grid;
792   }
793
794   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
795                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
796   {
797      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
798        ERROR("CGrid* CGrid::generateId(...)",
799              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
800              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
801
802      std::ostringstream id;
803
804      if (domains.empty() && axis.empty() && !scalars.empty())
805        id << "__scalar_";
806
807      if (0 != (domains.size() + axis.size() + scalars.size()))
808      {
809        id << "__grid";
810
811        if (0 == axisDomainOrder.numElements())
812        {
813          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
814          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
815          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
816        }
817        else
818        {
819          size_t iDomain = 0, iAxis = 0, iScalar = 0;
820          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
821          {
822            if (2 == axisDomainOrder(i))
823              id << "_" << domains[iDomain++]->getId();
824            else if (1 == axisDomainOrder(i))
825              id << "_" << axis[iAxis++]->getId();
826            else
827              id << "_" << scalars[iScalar++]->getId();
828          }
829        }
830
831        id << "__";
832      }
833
834      return id.str();
835   }
836
837   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
838   {
839     StdString idSrc  = gridSrc->getId();
840     StdString idDest = gridDest->getId();
841
842     std::ostringstream id;
843     id << idSrc << "__" << idDest;
844
845     return id.str();
846   }
847
848   //----------------------------------------------------------------
849
850   CDomainGroup* CGrid::getVirtualDomainGroup() const
851   {
852     return this->vDomainGroup_;
853   }
854
855   CAxisGroup* CGrid::getVirtualAxisGroup() const
856   {
857     return this->vAxisGroup_;
858   }
859
860   CScalarGroup* CGrid::getVirtualScalarGroup() const
861   {
862     return this->vScalarGroup_;
863   }
864
865   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
866   {
867     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
868     StdSize numElements = stored.numElements();
869     for (StdSize n = 0; n < numElements; ++n)
870     {
871       field[out_i(n)] = stored(n);
872     }
873   }
874
875   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
876   {
877     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
878     StdSize numElements = stored.numElements();
879     for (StdSize n = 0; n < numElements; ++n)
880     {
881       stored(n) = field[out_i(n)];
882     }
883   }
884
885   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
886   {
887     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
888     StdSize numElements = stored.numElements();
889     for (StdSize n = 0; n < numElements; ++n)
890     {
891       field[out_i(n)] = stored(n);
892     }
893   }
894
895   //----------------------------------------------------------------
896
897   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
898   {
899      const StdSize size = storeIndex_client.numElements();
900
901      stored.resize(size);
902      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
903   }
904
905   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
906   {
907      const StdSize size = storeIndex_client.numElements();
908
909      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
910   }
911
912  void CGrid::computeIndexScalarGrid()
913  {
914    CContext* context = CContext::getCurrent();
915    CContextClient* client=context->client;
916
917    storeIndex_client.resize(1);
918    storeIndex_client(0) = 0;
919    if (0 == client->clientRank)
920    {
921      for (int rank = 0; rank < client->serverSize; ++rank)
922        connectedDataSize_[rank] = 1;
923    }
924    isDataDistributed_ = false;
925  }
926
927  void CGrid::computeCompressedIndex()
928  {
929    compressedOutIndexFromClient = outIndexFromClient;
930
931    std::map<size_t, size_t> indexes;
932
933    {
934      std::map<int, CArray<size_t,1> >::const_iterator it = compressedOutIndexFromClient.begin();
935      std::map<int, CArray<size_t,1> >::const_iterator itEnd = compressedOutIndexFromClient.end();
936      for (; it != itEnd; ++it)
937      {
938        for (int i = 0; i < it->second.numElements(); ++i)
939          indexes.insert(std::make_pair(it->second(i), 0));
940      }
941    }
942
943    {
944      std::map<size_t, size_t>::iterator it = indexes.begin();
945      std::map<size_t, size_t>::iterator itEnd = indexes.end();
946      for (size_t i = 0; it != itEnd; ++it, ++i)
947        it->second = i;
948    }
949
950    {
951      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
952      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
953      for (; it != itEnd; ++it)
954      {
955        for (int i = 0; i < it->second.numElements(); ++i)
956          it->second(i) = indexes[it->second(i)];
957      }
958    }
959  }
960
961  void CGrid::sendIndexScalarGrid()
962  {
963    CContext* context = CContext::getCurrent();
964    CContextClient* client = context->client;
965
966    CEventClient event(getType(), EVENT_ID_INDEX);
967    list<CMessage> listMsg;
968    list<CArray<size_t,1> > listOutIndex;
969
970    if (0 == client->clientRank)
971    {
972      for (int rank = 0; rank < client->serverSize; ++rank)
973      {
974        int nb = 1;
975        storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(nb)));
976        listOutIndex.push_back(CArray<size_t,1>(nb));
977
978        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
979        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
980
981        for (int k = 0; k < nb; ++k)
982        {
983          outGlobalIndexOnServer(k) = 0;
984          outLocalIndexToServer(k)  = 0;
985        }
986
987        listMsg.push_back(CMessage());
988        listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
989
990        event.push(rank, 1, listMsg.back());
991      }
992
993      client->sendEvent(event);
994    }
995    else
996      client->sendEvent(event);
997  }
998
999  void CGrid::sendIndex(void)
1000  {
1001    CContext* context = CContext::getCurrent();
1002    CContextClient* client = context->client;
1003
1004    CEventClient event(getType(), EVENT_ID_INDEX);
1005    int rank;
1006    list<CMessage> listMsg;
1007    list<CArray<size_t,1> > listOutIndex;
1008    const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
1009    CDistributionClient::GlobalLocalDataMap::const_iterator itIndex = globalLocalIndexSendToServer.begin(),
1010                                                           iteIndex = globalLocalIndexSendToServer.end();
1011
1012    if (!doGridHaveDataDistributed())
1013    {
1014      if (0 == client->clientRank)
1015      {
1016        int indexSize = globalLocalIndexSendToServer.size();
1017        CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1018        CArray<int,1> outLocalIndexToServer(indexSize);
1019        for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1020        {
1021          outGlobalIndexOnServer(idx) = itIndex->first;
1022          outLocalIndexToServer(idx) = itIndex->second;
1023        }
1024
1025        for (rank = 0; rank < client->serverSize; ++rank)
1026        {
1027          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1028          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1029
1030          listMsg.push_back(CMessage());
1031          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1032
1033          event.push(rank, 1, listMsg.back());
1034        }
1035
1036        client->sendEvent(event);
1037      }
1038      else
1039        client->sendEvent(event);
1040    }
1041    else
1042    {
1043      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
1044      itGlobalMap = globalIndexOnServer_.begin();
1045      iteGlobalMap = globalIndexOnServer_.end();
1046
1047      std::map<int,std::vector<int> >localIndexTmp;
1048      std::map<int,std::vector<size_t> > globalIndexTmp;
1049      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1050      {
1051        int serverRank = itGlobalMap->first;
1052        int indexSize = itGlobalMap->second.size();
1053        const std::vector<size_t>& indexVec = itGlobalMap->second;
1054        for (int idx = 0; idx < indexSize; ++idx)
1055        {
1056          itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
1057          if (iteIndex != itIndex)
1058          {
1059            globalIndexTmp[serverRank].push_back(itIndex->first);
1060            localIndexTmp[serverRank].push_back(itIndex->second);
1061          }
1062        }
1063      }
1064
1065      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
1066      {
1067        rank = connectedServerRank_[ns];
1068        int nb = 0;
1069        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
1070          nb = globalIndexTmp[rank].size();
1071
1072        storeIndex_toSrv.insert(make_pair(rank, CArray<int,1>(nb)));
1073        listOutIndex.push_back(CArray<size_t,1>(nb));
1074
1075        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
1076        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1077
1078        for (int k = 0; k < nb; ++k)
1079        {
1080          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1081          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1082        }
1083
1084        listMsg.push_back(CMessage());
1085        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1086
1087        event.push(rank, nbSenders[rank], listMsg.back());
1088      }
1089
1090      client->sendEvent(event);
1091    }
1092  }
1093
1094  void CGrid::recvIndex(CEventServer& event)
1095  {
1096    string gridId;
1097    vector<int> ranks;
1098    vector<CBufferIn*> buffers;
1099
1100    list<CEventServer::SSubEvent>::iterator it;
1101    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1102    {
1103      ranks.push_back(it->rank);
1104      CBufferIn* buffer = it->buffer;
1105      *buffer >> gridId;
1106      buffers.push_back(buffer);
1107    }
1108    get(gridId)->recvIndex(ranks, buffers);
1109  }
1110
1111  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
1112                                         const std::vector<CAxis*>& axis,
1113                                         const std::vector<CScalar*>& scalars,
1114                                         const CArray<int,1>& axisDomainOrder)
1115  {
1116    globalDim_.resize(domains.size()*2+axis.size()+scalars.size());
1117    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1118    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1119    {
1120      if (2 == axisDomainOrder(i))
1121      {
1122        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1123        {
1124          positionDimensionDistributed_ = idx;
1125        }
1126        else
1127        {
1128          positionDimensionDistributed_ = idx +1;
1129        }
1130
1131        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
1132        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
1133
1134        ++idxDomain;
1135        idx += 2;
1136      }
1137      else if (1 == axisDomainOrder(i))
1138      {
1139        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
1140        ++idxAxis;
1141        ++idx;
1142      }
1143      else
1144      {
1145        globalDim_[idx] = 1;
1146        ++idxScalar;
1147        ++idx;
1148      }
1149    }
1150  }
1151
1152  std::vector<int> CGrid::getGlobalDimension()
1153  {
1154    return globalDim_;
1155  }
1156
1157  bool CGrid::isScalarGrid() const
1158  {
1159    return (axisList_.empty() && domList_.empty());
1160  }
1161
1162  /*!
1163    Verify whether one server need to write data
1164    There are some cases on which one server has nodata to write. For example, when we
1165    just only want to zoom on a domain.
1166  */
1167  bool CGrid::doGridHaveDataToWrite()
1168  {
1169     return (0 != writtenDataSize_);
1170  }
1171
1172  /*!
1173    Return size of data which is written on each server
1174    Whatever dimension of a grid, data which are written on server must be presented as
1175    an one dimension array.
1176    \return size of data written on server
1177  */
1178  size_t CGrid::getWrittenDataSize() const
1179  {
1180    return writtenDataSize_;
1181  }
1182
1183  /*!
1184    Returns the number of indexes written by each server.
1185    \return the number of indexes written by each server
1186  */
1187  int CGrid::getNumberWrittenIndexes() const
1188  {
1189    return numberWrittenIndexes_;
1190  }
1191
1192  /*!
1193    Returns the total number of indexes written by the servers.
1194    \return the total number of indexes written by the servers
1195  */
1196  int CGrid::getTotalNumberWrittenIndexes() const
1197  {
1198    return totalNumberWrittenIndexes_;
1199  }
1200
1201  /*!
1202    Returns the offset of indexes written by each server.
1203    \return the offset of indexes written by each server
1204  */
1205  int CGrid::getOffsetWrittenIndexes() const
1206  {
1207    return offsetWrittenIndexes_;
1208  }
1209
1210  CDistributionServer* CGrid::getDistributionServer()
1211  {
1212    return serverDistribution_;
1213  }
1214
1215  CDistributionClient* CGrid::getDistributionClient()
1216  {
1217    return clientDistribution_;
1218  }
1219
1220  bool CGrid::doGridHaveDataDistributed()
1221  {
1222    if (isScalarGrid()) return false;
1223    else
1224      return isDataDistributed_;
1225  }
1226
1227  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1228  {
1229    CContext* context = CContext::getCurrent();
1230    CContextServer* server = context->server;
1231    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
1232    connectedServerRank_ = ranks;
1233
1234    for (int n = 0; n < ranks.size(); n++)
1235    {
1236      int rank = ranks[n];
1237      CBufferIn& buffer = *buffers[n];
1238
1239      buffer >> isDataDistributed_ >> isCompressible_;
1240      size_t dataSize = 0;
1241
1242      if (isScalarGrid())
1243      {
1244        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
1245        CArray<size_t,1> outIndex;
1246        buffer >> outIndex;
1247        outIndexFromClient.insert(std::make_pair(rank, outIndex));
1248        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
1249        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1250                                                      nZoomBeginGlobal, nGlob);
1251        return;
1252      }
1253
1254      if (0 == serverDistribution_)
1255      {
1256        int idx = 0, numElement = axis_domain_order.numElements();
1257        int ssize = numElement;
1258        std::vector<int> indexMap(numElement);
1259        for (int i = 0; i < numElement; ++i)
1260        {
1261          indexMap[i] = idx;
1262          if (2 == axis_domain_order(i))
1263          {
1264            ++ssize;
1265            idx += 2;
1266          }
1267          else
1268            ++idx;
1269        }
1270
1271        int axisId = 0, domainId = 0, scalarId = 0;
1272        std::vector<CDomain*> domainList = getDomains();
1273        std::vector<CAxis*> axisList = getAxis();
1274        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
1275        for (int i = 0; i < numElement; ++i)
1276        {
1277          if (2 == axis_domain_order(i)) //domain
1278          {
1279            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
1280            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
1281            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
1282            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1283
1284            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
1285            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
1286            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
1287            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1288            ++domainId;
1289          }
1290          else if (1 == axis_domain_order(i)) // axis
1291          {
1292            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1293            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1294            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
1295            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1296            ++axisId;
1297          }
1298          else // scalar
1299          {
1300            nZoomBegin[indexMap[i]] = 0;
1301            nZoomSize[indexMap[i]]  = 1;
1302            nZoomBeginGlobal[indexMap[i]] = 0;
1303            nGlob[indexMap[i]] = 1;
1304            ++scalarId;
1305          }
1306        }
1307        dataSize = 1;
1308        for (int i = 0; i < nZoomSize.size(); ++i)
1309          dataSize *= nZoomSize[i];
1310
1311        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1312                                                      nZoomBeginGlobal, nGlob);
1313      }
1314
1315      CArray<size_t,1> outIndex;
1316      buffer >> outIndex;
1317      if (isDataDistributed_)
1318        serverDistribution_->computeLocalIndex(outIndex);
1319      else
1320      {
1321        dataSize = outIndex.numElements();
1322        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
1323      }
1324      writtenDataSize_ += dataSize;
1325
1326      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1327      connectedDataSize_[rank] = outIndex.numElements();
1328      numberWrittenIndexes_ += outIndex.numElements();
1329    }
1330
1331    if (isDataDistributed_)
1332    {
1333      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1334      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1335      offsetWrittenIndexes_ -= numberWrittenIndexes_;
1336    }
1337    else
1338      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1339
1340    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1341  }
1342
1343   /*!
1344   \brief Dispatch event received from client
1345      Whenever a message is received in buffer of server, it will be processed depending on
1346   its event type. A new event type should be added in the switch list to make sure
1347   it processed on server side.
1348   \param [in] event: Received message
1349   */
1350  bool CGrid::dispatchEvent(CEventServer& event)
1351  {
1352
1353    if (SuperClass::dispatchEvent(event)) return true;
1354    else
1355    {
1356      switch(event.type)
1357      {
1358        case EVENT_ID_INDEX :
1359          recvIndex(event);
1360          return true;
1361          break;
1362
1363         case EVENT_ID_ADD_DOMAIN :
1364           recvAddDomain(event);
1365           return true;
1366           break;
1367
1368         case EVENT_ID_ADD_AXIS :
1369           recvAddAxis(event);
1370           return true;
1371           break;
1372
1373         case EVENT_ID_ADD_SCALAR :
1374           recvAddScalar(event);
1375           return true;
1376           break;
1377        default :
1378          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1379                << "Unknown Event");
1380          return false;
1381      }
1382    }
1383  }
1384
1385   ///---------------------------------------------------------------
1386
1387   CDomain* CGrid::addDomain(const std::string& id)
1388   {
1389     order_.push_back(2);
1390     axis_domain_order.resize(order_.size());
1391     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1392     return vDomainGroup_->createChild(id);
1393   }
1394
1395   CAxis* CGrid::addAxis(const std::string& id)
1396   {
1397     order_.push_back(1);
1398     axis_domain_order.resize(order_.size());
1399     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1400     return vAxisGroup_->createChild(id);
1401   }
1402
1403   CScalar* CGrid::addScalar(const std::string& id)
1404   {
1405     order_.push_back(0);
1406     axis_domain_order.resize(order_.size());
1407     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1408     return vScalarGroup_->createChild(id);
1409   }
1410
1411   //! Change virtual field group to a new one
1412   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1413   {
1414      this->vDomainGroup_ = newVDomainGroup;
1415   }
1416
1417   //! Change virtual variable group to new one
1418   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1419   {
1420      this->vAxisGroup_ = newVAxisGroup;
1421   }
1422
1423   //! Change virtual variable group to new one
1424   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1425   {
1426      this->vScalarGroup_ = newVScalarGroup;
1427   }
1428
1429   //----------------------------------------------------------------
1430   //! Create virtual field group, which is done normally on initializing file
1431   void CGrid::setVirtualDomainGroup(void)
1432   {
1433      this->setVirtualDomainGroup(CDomainGroup::create());
1434   }
1435
1436   //! Create virtual variable group, which is done normally on initializing file
1437   void CGrid::setVirtualAxisGroup(void)
1438   {
1439      this->setVirtualAxisGroup(CAxisGroup::create());
1440   }
1441
1442   //! Create virtual variable group, which is done normally on initializing file
1443   void CGrid::setVirtualScalarGroup(void)
1444   {
1445      this->setVirtualScalarGroup(CScalarGroup::create());
1446   }
1447
1448   /*!
1449   \brief Send a message to create a domain on server side
1450   \param[in] id String identity of domain that will be created on server
1451   */
1452   void CGrid::sendAddDomain(const string& id)
1453   {
1454    CContext* context=CContext::getCurrent();
1455
1456    if (! context->hasServer )
1457    {
1458       CContextClient* client=context->client;
1459
1460       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1461       if (client->isServerLeader())
1462       {
1463         CMessage msg;
1464         msg<<this->getId();
1465         msg<<id;
1466         const std::list<int>& ranks = client->getRanksServerLeader();
1467         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1468           event.push(*itRank,1,msg);
1469         client->sendEvent(event);
1470       }
1471       else client->sendEvent(event);
1472    }
1473   }
1474
1475   /*!
1476   \brief Send a message to create an axis on server side
1477   \param[in] id String identity of axis that will be created on server
1478   */
1479   void CGrid::sendAddAxis(const string& id)
1480   {
1481    CContext* context=CContext::getCurrent();
1482
1483    if (! context->hasServer )
1484    {
1485       CContextClient* client=context->client;
1486
1487       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1488       if (client->isServerLeader())
1489       {
1490         CMessage msg;
1491         msg<<this->getId();
1492         msg<<id;
1493         const std::list<int>& ranks = client->getRanksServerLeader();
1494         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1495           event.push(*itRank,1,msg);
1496         client->sendEvent(event);
1497       }
1498       else client->sendEvent(event);
1499    }
1500   }
1501
1502   /*!
1503   \brief Send a message to create a scalar on server side
1504   \param[in] id String identity of scalar that will be created on server
1505   */
1506   void CGrid::sendAddScalar(const string& id)
1507   {
1508    CContext* context=CContext::getCurrent();
1509
1510    if (! context->hasServer )
1511    {
1512       CContextClient* client=context->client;
1513
1514       CEventClient event(this->getType(),EVENT_ID_ADD_SCALAR);
1515       if (client->isServerLeader())
1516       {
1517         CMessage msg;
1518         msg<<this->getId();
1519         msg<<id;
1520         const std::list<int>& ranks = client->getRanksServerLeader();
1521         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1522           event.push(*itRank,1,msg);
1523         client->sendEvent(event);
1524       }
1525       else client->sendEvent(event);
1526    }
1527   }
1528
1529   /*!
1530   \brief Receive a message annoucing the creation of a domain on server side
1531   \param[in] event Received event
1532   */
1533   void CGrid::recvAddDomain(CEventServer& event)
1534   {
1535
1536      CBufferIn* buffer = event.subEvents.begin()->buffer;
1537      string id;
1538      *buffer >> id;
1539      get(id)->recvAddDomain(*buffer);
1540   }
1541
1542   /*!
1543   \brief Receive a message annoucing the creation of a domain on server side
1544   \param[in] buffer Buffer containing message
1545   */
1546   void CGrid::recvAddDomain(CBufferIn& buffer)
1547   {
1548      string id;
1549      buffer >> id;
1550      addDomain(id);
1551   }
1552
1553   /*!
1554   \brief Receive a message annoucing the creation of an axis on server side
1555   \param[in] event Received event
1556   */
1557   void CGrid::recvAddAxis(CEventServer& event)
1558   {
1559
1560      CBufferIn* buffer = event.subEvents.begin()->buffer;
1561      string id;
1562      *buffer >> id;
1563      get(id)->recvAddAxis(*buffer);
1564   }
1565
1566   /*!
1567   \brief Receive a message annoucing the creation of an axis on server side
1568   \param[in] buffer Buffer containing message
1569   */
1570   void CGrid::recvAddAxis(CBufferIn& buffer)
1571   {
1572      string id;
1573      buffer >> id;
1574      addAxis(id);
1575   }
1576
1577   /*!
1578   \brief Receive a message annoucing the creation of an scalar on server side
1579   \param[in] event Received event
1580   */
1581   void CGrid::recvAddScalar(CEventServer& event)
1582   {
1583
1584      CBufferIn* buffer = event.subEvents.begin()->buffer;
1585      string id;
1586      *buffer >> id;
1587      get(id)->recvAddScalar(*buffer);
1588   }
1589
1590   /*!
1591   \brief Receive a message annoucing the creation of an scalar on server side
1592   \param[in] buffer Buffer containing message
1593   */
1594   void CGrid::recvAddScalar(CBufferIn& buffer)
1595   {
1596      string id;
1597      buffer >> id;
1598      addScalar(id);
1599   }
1600
1601  /*!
1602  \brief Solve domain and axis references
1603  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1604  all attributes from their parents, they should be processed with this function
1605  \param[in] apply inherit all attributes of parents (true)
1606  */
1607  void CGrid::solveDomainAxisRefInheritance(bool apply)
1608  {
1609    CContext* context = CContext::getCurrent();
1610    unsigned int vecSize, i;
1611    std::vector<StdString>::iterator it, itE;
1612    setDomainList();
1613    it = domList_.begin(); itE = domList_.end();
1614    for (; it != itE; ++it)
1615    {
1616      CDomain* pDom = CDomain::get(*it);
1617      if (context->hasClient)
1618      {
1619        pDom->solveRefInheritance(apply);
1620        pDom->solveInheritanceTransformation();
1621      }
1622    }
1623
1624    setAxisList();
1625    it = axisList_.begin(); itE = axisList_.end();
1626    for (; it != itE; ++it)
1627    {
1628      CAxis* pAxis = CAxis::get(*it);
1629      if (context->hasClient)
1630      {
1631        pAxis->solveRefInheritance(apply);
1632        pAxis->solveInheritanceTransformation();
1633      }
1634    }
1635
1636    setScalarList();
1637    it = scalarList_.begin(); itE = scalarList_.end();
1638    for (; it != itE; ++it)
1639    {
1640      CScalar* pScalar = CScalar::get(*it);
1641      if (context->hasClient)
1642      {
1643        pScalar->solveRefInheritance(apply);
1644        pScalar->solveInheritanceTransformation();
1645      }
1646    }
1647  }
1648
1649  bool CGrid::isTransformed()
1650  {
1651    return isTransformed_;
1652  }
1653
1654  void CGrid::setTransformed()
1655  {
1656    isTransformed_ = true;
1657  }
1658
1659  CGridTransformation* CGrid::getTransformations()
1660  {
1661    return transformations_;
1662  }
1663
1664  void CGrid::addTransGridSource(CGrid* gridSrc)
1665  {
1666    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1667      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1668  }
1669
1670  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1671  {
1672    return gridSrc_;
1673  }
1674
1675  /*!
1676     Complete all the necessary (and lacking) attributes of a grid
1677     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1678  */
1679  void CGrid::completeGrid(CGrid* transformGridSrc)
1680  {
1681    if (0 != transformGridSrc)
1682    {
1683      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1684      {
1685        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1686             << "Two grids have different dimension size"
1687             << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1688             << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1689      }
1690    }
1691
1692    if (isGenerated()) return;
1693    setGenerated();
1694
1695    CGridGenerate gridGenerate(this, transformGridSrc);
1696    gridGenerate.completeGrid();
1697  }
1698
1699  bool CGrid::isGenerated()
1700  {
1701    return isGenerated_;
1702  }
1703
1704  void CGrid::setGenerated()
1705  {
1706    isGenerated_ = true;
1707  }
1708
1709  void CGrid::transformGrid(CGrid* transformGridSrc)
1710  {
1711    if (!transformGridSrc)
1712      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1713            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1714
1715    if (isTransformed()) return;
1716    setTransformed();
1717    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1718    {
1719      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1720           << "Two grids have different dimension size"
1721           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1722           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1723    }
1724    else
1725    {
1726//      int ssize = axis_domain_order.numElements();
1727//      for (int i = 0; i < ssize; ++i)
1728//        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1729//          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1730//                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1731//                << " don't have elements in the same order");
1732    }
1733
1734    transformations_ = new CGridTransformation(this, transformGridSrc);
1735    transformations_->computeAll();
1736    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1737
1738    // Ok, now need to compute index of grid source
1739    transformGridSrc->checkMaskIndex(false);
1740  }
1741
1742  bool CGrid::hasTransform()
1743  {
1744    return hasTransform_;
1745  }
1746
1747  /*!
1748  \brief Get the list of domain pointers
1749  \return list of domain pointers
1750  */
1751  std::vector<CDomain*> CGrid::getDomains()
1752  {
1753    std::vector<CDomain*> domList;
1754    if (!domList_.empty())
1755    {
1756      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1757    }
1758    return domList;
1759  }
1760
1761  /*!
1762  \brief Get the list of  axis pointers
1763  \return list of axis pointers
1764  */
1765  std::vector<CAxis*> CGrid::getAxis()
1766  {
1767    std::vector<CAxis*> aList;
1768    if (!axisList_.empty())
1769      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1770
1771    return aList;
1772  }
1773
1774  /*!
1775  \brief Get the list of  axis pointers
1776  \return list of axis pointers
1777  */
1778  std::vector<CScalar*> CGrid::getScalars()
1779  {
1780    std::vector<CScalar*> sList;
1781    if (!scalarList_.empty())
1782      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
1783
1784    return sList;
1785  }
1786
1787  /*!
1788  \brief Set domain(s) of a grid from a list
1789  \param[in] domains list of domains
1790  */
1791  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1792  {
1793    if (isDomListSet) return;
1794    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1795    if (!domains.empty() && domList.empty())
1796    {
1797      for (int i = 0; i < domains.size(); ++i)
1798        this->getVirtualDomainGroup()->addChild(domains[i]);
1799      domList = this->getVirtualDomainGroup()->getAllChildren();
1800    }
1801
1802    if (!domList.empty())
1803    {
1804      int sizeDom = domList.size();
1805      domList_.resize(sizeDom);
1806      for (int i = 0; i < sizeDom; ++i)
1807      {
1808        domList_[i] = domList[i]->getId();
1809      }
1810      isDomListSet = true;
1811    }
1812
1813  }
1814
1815  /*!
1816  \brief Set axis(s) of a grid from a list
1817  \param[in] axis list of axis
1818  */
1819  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1820  {
1821    if (isAxisListSet) return;
1822    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1823    if (!axis.empty() && aList.empty())
1824    {
1825      for (int i = 0; i < axis.size(); ++i)
1826        this->getVirtualAxisGroup()->addChild(axis[i]);
1827      aList = this->getVirtualAxisGroup()->getAllChildren();
1828    }
1829
1830    if (!aList.empty())
1831    {
1832      int sizeAxis = aList.size();
1833      axisList_.resize(sizeAxis);
1834      for (int i = 0; i < sizeAxis; ++i)
1835      {
1836        axisList_[i] = aList[i]->getId();
1837      }
1838      isAxisListSet = true;
1839    }
1840  }
1841
1842  /*!
1843  \brief Set scalar(s) of a grid from a list
1844  \param[in] scalars list of scalars
1845  */
1846  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
1847  {
1848    if (isScalarListSet) return;
1849    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
1850    if (!scalars.empty() && sList.empty())
1851    {
1852      for (int i = 0; i < scalars.size(); ++i)
1853        this->getVirtualScalarGroup()->addChild(scalars[i]);
1854      sList = this->getVirtualScalarGroup()->getAllChildren();
1855    }
1856
1857    if (!sList.empty())
1858    {
1859      int sizeScalar = sList.size();
1860      scalarList_.resize(sizeScalar);
1861      for (int i = 0; i < sizeScalar; ++i)
1862      {
1863        scalarList_[i] = sList[i]->getId();
1864      }
1865      isScalarListSet = true;
1866    }
1867  }
1868
1869  /*!
1870  \brief Get list of id of domains
1871  \return id list of domains
1872  */
1873  std::vector<StdString> CGrid::getDomainList()
1874  {
1875    setDomainList();
1876    return domList_;
1877  }
1878
1879  /*!
1880  \brief Get list of id of axis
1881  \return id list of axis
1882  */
1883  std::vector<StdString> CGrid::getAxisList()
1884  {
1885    setAxisList();
1886    return axisList_;
1887  }
1888
1889  /*!
1890  \brief Get list of id of scalar
1891  \return id list of scalar
1892  */
1893  std::vector<StdString> CGrid::getScalarList()
1894  {
1895    setScalarList();
1896    return scalarList_;
1897  }
1898
1899  /*!
1900    Send all attributes of domains from client to server
1901  */
1902  void CGrid::sendAllDomains()
1903  {
1904    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1905    int dSize = domList.size();
1906    for (int i = 0; i < dSize; ++i)
1907    {
1908      sendAddDomain(domList[i]->getId());
1909      domList[i]->sendAllAttributesToServer();
1910    }
1911  }
1912
1913  /*!
1914    Send all attributes of axis from client to server
1915  */
1916  void CGrid::sendAllAxis()
1917  {
1918    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1919    int aSize = aList.size();
1920
1921    for (int i = 0; i < aSize; ++i)
1922    {
1923      sendAddAxis(aList[i]->getId());
1924      aList[i]->sendAllAttributesToServer();
1925    }
1926  }
1927
1928  /*!
1929    Send all attributes of scalars from client to server
1930  */
1931  void CGrid::sendAllScalars()
1932  {
1933    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
1934    int sSize = sList.size();
1935
1936    for (int i = 0; i < sSize; ++i)
1937    {
1938      sendAddScalar(sList[i]->getId());
1939      sList[i]->sendAllAttributesToServer();
1940    }
1941  }
1942
1943  /*!
1944    Parse a grid, for now, it contains only domain, axis and scalar
1945  */
1946  void CGrid::parse(xml::CXMLNode& node)
1947  {
1948    SuperClass::parse(node);
1949
1950    if (node.goToChildElement())
1951    {
1952      StdString domainName("domain");
1953      StdString axisName("axis");
1954      StdString scalarName("scalar");
1955      do
1956      {
1957        if (node.getElementName() == domainName) {
1958          order_.push_back(2);
1959          this->getVirtualDomainGroup()->parseChild(node);
1960        }
1961        if (node.getElementName() == axisName) {
1962          order_.push_back(1);
1963          this->getVirtualAxisGroup()->parseChild(node);
1964        }
1965        if (node.getElementName() == scalarName) {
1966          order_.push_back(0);
1967          this->getVirtualScalarGroup()->parseChild(node);
1968        }
1969      } while (node.goToNextElement());
1970      node.goToParentElement();
1971    }
1972
1973    if (!order_.empty())
1974    {
1975      int sizeOrd = order_.size();
1976      axis_domain_order.resize(sizeOrd);
1977      for (int i = 0; i < sizeOrd; ++i)
1978      {
1979        axis_domain_order(i) = order_[i];
1980      }
1981    }
1982
1983    setDomainList();
1984    setAxisList();
1985    setScalarList();
1986   }
1987} // namespace xios
Note: See TracBrowser for help on using the repository browser.