source: XIOS/dev/dev_olga/src/node/grid.cpp @ 1009

Last change on this file since 1009 was 1009, checked in by oabramkina, 7 years ago

First working version with compression by secondary servers.

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