source: XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp @ 1294

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

Improvements for the secondary server: each grid is only sent to secondary-server pools that need it.

  • 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: 87.3 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      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
34      , transformations_(0), isTransformed_(false)
35      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
36      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
37      , computedWrittenIndex_(false)
38      , clients()
39   {
40     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
41     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
42     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
43   }
44
45   CGrid::CGrid(const StdString& id)
46      : CObjectTemplate<CGrid>(id), CGridAttributes()
47      , isChecked(false), isDomainAxisChecked(false)
48      , vDomainGroup_(), domList_(), isDomListSet(false)
49      , vAxisGroup_(), axisList_(), isAxisListSet(false)
50      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
51      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
52      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
53      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
54      , transformations_(0), isTransformed_(false)
55      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
56      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
57      , computedWrittenIndex_(false)
58      , clients()
59   {
60     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
61     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
62     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
63   }
64
65   CGrid::~CGrid(void)
66   {
67    if (0 != clientDistribution_) delete clientDistribution_;
68    if (0 != serverDistribution_) delete serverDistribution_;
69    if (0 != clientServerMap_) delete clientServerMap_;
70    if (0 != transformations_) delete transformations_;
71   }
72
73   ///---------------------------------------------------------------
74
75   StdString CGrid::GetName(void)    { return StdString("grid"); }
76   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
77   ENodeType CGrid::GetType(void)    { return eGrid; }
78
79
80   StdSize CGrid::getDimension(void)
81   {
82      return getGlobalDimension().size();
83   }
84
85   //---------------------------------------------------------------
86
87   StdSize CGrid::getDataSize(void) const
88   {
89     StdSize retvalue = 1;
90     if (!isScalarGrid())
91     {
92       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
93       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];       
94     }
95     return retvalue;
96   }
97
98   /*!
99    * Compute the minimum buffer size required to send the attributes to the server(s).
100    *
101    * \return A map associating the server rank with its minimum buffer size.
102    * TODO: Refactor code
103    */
104   std::map<int, StdSize> CGrid::getAttributesBufferSize(CContextClient* client)
105   {
106     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
107
108     // The grid indexes require a similar size as the actual data
109     std::map<int, StdSize> dataSizes = getDataBufferSize(client);
110     // for (size_t i = 0; i < dataSizes.size(); ++i)
111     // {
112       std::map<int, StdSize>::iterator it, itE = dataSizes.end();
113       for (it = dataSizes.begin(); it != itE; ++it)
114       {
115         it->second += 2 * sizeof(bool);
116         if (it->second > attributesSizes[it->first])
117           attributesSizes[it->first] = it->second;
118       }
119     // }
120
121     
122     // Account for the axis attributes
123     std::vector<CAxis*> axisList = getAxis();
124     for (size_t i = 0; i < axisList.size(); ++i)
125     {
126       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client);       
127       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
128       {
129         if (it->second > attributesSizes[it->first])
130           attributesSizes[it->first] = it->second;
131       }
132     }
133
134     // Account for the domain attributes
135     std::vector<CDomain*> domList = getDomains();
136     for (size_t i = 0; i < domList.size(); ++i)
137     {
138       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize(client);
139       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
140       {
141         if (it->second > attributesSizes[it->first])
142           attributesSizes[it->first] = it->second;
143       }
144     }
145
146     return attributesSizes;
147  }
148
149   /*!
150    * Compute the minimum buffer size required to send the data.
151    * \param client contextClient used to determine the size of connected receivers
152    * \param id the id used to tag the data
153    * \return A map associating the sender rank with its minimum buffer size.
154    */
155   std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/)
156   {     
157     // The record index is sometimes sent along with the data but we always
158     // include it in the size calculation for the sake of simplicity
159     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() 
160                                                       + 2 * sizeof(size_t) 
161                                                       + sizeof(size_t);
162     // CContext* context = CContext::getCurrent();
163     // int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
164     // std::vector<std::map<int, StdSize> > dataSizes(nbSrvPools);
165     // for (int p = 0; p < nbSrvPools; ++p)
166     // {
167     //   std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[client].end();
168     //   for (size_t k = 0; k < connectedServerRank_[p].size(); ++k)
169     //   {
170     //     int rank = connectedServerRank_[p][k];
171     //     std::map<int, size_t>::const_iterator it = connectedDataSize_[client].find(rank);
172     //     size_t count = (it != itEnd) ? it->second : 0;
173
174     //     dataSizes[p].insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
175     //   }
176       
177     // }
178
179     std::map<int, StdSize> dataSizes;
180     int receiverSize = client->serverSize;
181     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[receiverSize].end();
182     for (size_t k = 0; k < connectedServerRank_[receiverSize].size(); ++k)
183     {
184       int rank = connectedServerRank_[receiverSize][k];
185       std::map<int, size_t>::const_iterator it = connectedDataSize_[receiverSize].find(rank);
186       size_t count = (it != itEnd) ? it->second : 0;
187
188       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
189     }
190
191     return dataSizes;
192   }
193
194   size_t CGrid::getGlobalWrittenSize(void)
195   {
196         std::vector<CDomain*> domainP = this->getDomains();
197     std::vector<CAxis*> axisP = this->getAxis();
198     
199     size_t globalGridSize=1 ;
200     for (std::vector<CDomain*>::iterator it=domainP.begin(); it!=domainP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
201     for (std::vector<CAxis*>::iterator it=axisP.begin(); it!=axisP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
202     return globalGridSize ;
203   }
204   
205   
206   void CGrid::checkAttributesAfterTransformation()
207   {
208      setAxisList();
209      std::vector<CAxis*> axisListP = this->getAxis();
210      if (!axisListP.empty())
211      {
212        int idx = 0;
213        axisPositionInGrid_.resize(0);
214        for (int i = 0; i < axis_domain_order.numElements(); ++i)
215        {
216          int elementDimension = axis_domain_order(i);
217          if (1 == elementDimension)
218          {
219            axisPositionInGrid_.push_back(idx);
220            ++idx;
221          }
222          else if (2 == elementDimension) idx += 2;
223        }
224
225        for (int i = 0; i < axisListP.size(); ++i)
226        {
227          axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(),axisPositionInGrid_[i]);
228        }
229      }
230
231      setDomainList();
232      std::vector<CDomain*> domListP = this->getDomains();
233      if (!domListP.empty())
234      {
235        for (int i = 0; i < domListP.size(); ++i)
236        {
237          domListP[i]->checkAttributesOnClientAfterTransformation();
238        }
239      }
240   }
241
242   //---------------------------------------------------------------
243
244   /*!
245    * Test whether the data defined on the grid can be outputted in a compressed way.
246    *
247    * \return true if and only if a mask was defined for this grid
248    */
249   bool CGrid::isCompressible(void) const
250   {
251      return isCompressible_;
252   }
253
254   //---------------------------------------------------------------
255
256   void CGrid::addRelFileCompressed(const StdString& filename)
257   {
258      this->relFilesCompressed.insert(filename);
259   }
260
261   bool CGrid::isWrittenCompressed(const StdString& filename) const
262   {
263      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
264   }
265
266   //---------------------------------------------------------------
267   /*
268     Find all reference of grid's components and inherite attributes if necessary
269   */
270   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
271   {
272     if (this->isDomainAxisChecked) return;
273
274     this->solveScalarRef(areAttributesChecked);
275     this->solveAxisRef(areAttributesChecked);
276     this->solveDomainRef(areAttributesChecked);     
277     this->isDomainAxisChecked = areAttributesChecked;
278   }
279
280   /*
281     Go up hierachy reference and fill in the base reference with attributes of the children
282     This function should be only used after reading component's attributes from file
283   */
284   void CGrid::solveDomainAxisBaseRef()
285   {
286     if (this->hasDomainAxisBaseRef_) return;
287     // Account for the scalar attributes
288     std::vector<CScalar*> scalarList = getScalars();
289     for (size_t i = 0; i < scalarList.size(); ++i)
290     {
291       scalarList[i]->setAttributesReference();
292     }
293
294     // Account for the axis attributes
295     std::vector<CAxis*> axisList = getAxis();
296     for (size_t i = 0; i < axisList.size(); ++i)
297     {
298       axisList[i]->setAttributesReference();
299     }
300
301     // Account for the domain attributes
302     std::vector<CDomain*> domList = getDomains();
303     for (size_t i = 0; i < domList.size(); ++i)
304     {
305       domList[i]->setAttributesReference();
306     }
307
308     this->hasDomainAxisBaseRef_ = true;
309   }
310
311   void CGrid::checkEligibilityForCompressedOutput()
312   {
313     // We don't check if the mask is valid here, just if a mask has been defined at this point.
314     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
315   }
316
317   void CGrid::checkMaskIndex(bool doSendingIndex)
318   {
319     CContext* context = CContext::getCurrent();
320     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;   
321     nbSrvPools = 1; 
322     for (int p = 0; p < nbSrvPools; ++p)
323     {   
324       if (context->hasClient && this->isChecked && doSendingIndex && !isIndexSent) 
325       { 
326         if (isScalarGrid())
327           sendIndexScalarGrid();
328         else
329           sendIndex();
330         this->isIndexSent = true; 
331       }
332
333       // Not sure about this
334       //if (!(this->hasTransform() && !this->isTransformed()))
335       // this->isChecked = true;
336       //return;
337     }
338   
339     if (this->isChecked) return;
340     this->checkAttributesAfterTransformation();
341
342     // TODO: Transfer grid attributes
343     //if (!context->hasClient && context->hasServer) this->createMask();
344     this->computeIndex();
345
346     if (!(this->hasTransform() && !this->isTransformed()))
347      this->isChecked = true;
348
349     if (!(this->hasTransform() && (!this->isGenerated())))
350      this->isChecked = true;
351   }
352
353   /*
354     Create mask of grid from mask of its components
355   */
356   void CGrid::createMask(void)
357   {
358      using namespace std;
359      std::vector<CDomain*> domainP = this->getDomains();
360      std::vector<CAxis*> axisP = this->getAxis();
361      int dim = domainP.size() * 2 + axisP.size();
362
363      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
364      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
365      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
366      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
367
368      switch (dim) {
369        case 1:
370          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
371          break;
372        case 2:
373          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
374          break;
375        case 3:
376          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
377          break;
378        case 4:
379          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true);
380          break;
381        case 5:
382          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true);
383          break;
384        case 6:
385          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true);
386          break;
387        case 7:
388          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true);
389          break;
390        default:
391          break;
392      }
393   }
394
395   /*
396     Check validity of grid's mask by using the masks of its components
397   */
398   void CGrid::checkMask(void)
399   {
400      using namespace std;
401      std::vector<CDomain*> domainP = this->getDomains();
402      std::vector<CAxis*> axisP = this->getAxis();
403      int dim = domainP.size() * 2 + axisP.size();
404
405      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
406      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
407      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
408      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
409
410      switch (dim) {
411        case 1:
412          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
413          break;
414        case 2:
415          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
416          break;
417        case 3:
418          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
419          break;
420        case 4:
421          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order);
422          break;
423        case 5:
424          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order);
425          break;
426        case 6:
427          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order);
428          break;
429        case 7:
430          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order);
431          break;
432        default:
433          break;
434      }
435   }
436
437   /*
438     Modify value of mask in a certain index
439     This function can be used to correct the mask of grid after being constructed with createMask
440     \param [in] indexToModify
441     \param [in] modifyValue
442   */
443   void CGrid::modifyMask(const CArray<int,1>& indexToModify, bool modifyValue)
444   {
445      using namespace std;
446      std::vector<CDomain*> domainP = this->getDomains();
447      std::vector<CAxis*> axisP = this->getAxis();
448      int dim = domainP.size() * 2 + axisP.size();
449
450      switch (dim) {
451        case 0:
452          modifyGridMask(mask_0d, indexToModify, modifyValue);
453          break;
454        case 1:
455          modifyGridMask(mask_1d, indexToModify, modifyValue);
456          break;
457        case 2:
458          modifyGridMask(mask_2d, indexToModify, modifyValue);
459          break;
460        case 3:
461          modifyGridMask(mask_3d, indexToModify, modifyValue);
462          break;
463        case 4:
464          modifyGridMask(mask_4d, indexToModify, modifyValue);
465          break;
466        case 5:
467          modifyGridMask(mask_5d, indexToModify, modifyValue);
468          break;
469        case 6:
470          modifyGridMask(mask_6d, indexToModify, modifyValue);
471          break;
472        case 7:
473          modifyGridMask(mask_7d, indexToModify, modifyValue);
474          break;
475        default:
476          break;
477      }
478   }
479
480   /*
481     Change the mask size. This function is used on reconstructing mask in server side
482     \param [in] newDimensionSize
483     \param [in] newValue
484   */
485   void CGrid::modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue)
486   {     
487      std::vector<CDomain*> domainP = this->getDomains();
488      std::vector<CAxis*> axisP = this->getAxis();           
489      int dim = domainP.size() * 2 + axisP.size();
490
491      switch (dim) {
492        case 0:
493          modifyGridMaskSize(mask_0d, newDimensionSize, newValue);
494          break;
495        case 1:
496          modifyGridMaskSize(mask_1d, newDimensionSize, newValue);
497          break;
498        case 2:
499          modifyGridMaskSize(mask_2d, newDimensionSize, newValue);
500          break;
501        case 3:
502          modifyGridMaskSize(mask_3d, newDimensionSize, newValue);
503          break;
504        case 4:
505          modifyGridMaskSize(mask_4d, newDimensionSize, newValue);
506          break;
507        case 5:
508          modifyGridMaskSize(mask_5d, newDimensionSize, newValue);
509          break;
510        case 6:
511          modifyGridMaskSize(mask_6d, newDimensionSize, newValue);
512          break;
513        case 7:
514          modifyGridMaskSize(mask_7d, newDimensionSize, newValue);
515          break;
516        default:
517          break;
518      }
519   }
520
521   //---------------------------------------------------------------
522
523   void CGrid::solveDomainRef(bool sendAtt)
524   {
525      setDomainList();
526      std::vector<CDomain*> domListP = this->getDomains();
527      if (!domListP.empty())
528      {
529        for (int i = 0; i < domListP.size(); ++i)
530        {
531          if (sendAtt) domListP[i]->sendCheckedAttributes();
532          else domListP[i]->checkAttributesOnClient();
533        }
534      }
535   }
536
537   //---------------------------------------------------------------
538
539   void CGrid::solveAxisRef(bool sendAtt)
540   {
541      setAxisList();
542      std::vector<CAxis*> axisListP = this->getAxis();
543      if (!axisListP.empty())
544      {
545        int idx = 0;
546        axisPositionInGrid_.resize(0);
547        for (int i = 0; i < axis_domain_order.numElements(); ++i)
548        {
549          int elementDimension = axis_domain_order(i);
550          if (1 == elementDimension)
551          {
552            axisPositionInGrid_.push_back(idx);
553            ++idx;
554          }
555          else if (2 == elementDimension) idx += 2;
556        }
557
558        for (int i = 0; i < axisListP.size(); ++i)
559        {
560          if (sendAtt)
561            axisListP[i]->sendCheckedAttributes(getGlobalDimension(),axisPositionInGrid_[i]);
562          else
563            axisListP[i]->checkAttributesOnClient();
564        }
565      }
566   }
567
568   //---------------------------------------------------------------
569
570   void CGrid::solveScalarRef(bool sendAtt)
571   {
572      setScalarList();
573      std::vector<CScalar*> scalarListP = this->getScalars();
574      if (!scalarListP.empty())
575      {
576        for (int i = 0; i < scalarListP.size(); ++i)
577        {
578          /*Nothing to do for now */
579//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
580//          else scalarListP[i]->checkAttributesOnClient();
581        }
582      }
583   }
584
585   /*!
586      Compute the index to for write data into a file
587   */
588   void CGrid::computeWrittenIndex()
589   {     
590      if (computedWrittenIndex_) return;
591      computedWrittenIndex_ = true;
592
593      if (isScalarGrid())
594      {
595        size_t nbWritten = 1;
596        int writtenIndex = 0;
597
598        localIndexToWriteOnClient.resize(nbWritten); 
599        localIndexToWriteOnServer.resize(nbWritten);
600        localIndexToWriteOnServer(0) = writtenIndex;
601        localIndexToWriteOnClient(0) = writtenIndex;
602       
603        return;
604      }
605
606      size_t nbWritten = 0, indGlo;
607      CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
608      CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(),
609                                                              ite = globalDataIndex.end(), it;   
610      const CDistributionServer::GlobalLocalMap& globalLocalIndex = serverDistribution_->getGlobalLocalIndex();                                                             
611      CDistributionServer::GlobalLocalMap::const_iterator itSrvb = globalLocalIndex.begin(),
612                                                          itSrve = globalLocalIndex.end(), itSrv;
613      for (it = itb; it != ite; ++it)
614      {
615        indGlo = it->first;
616        if (globalLocalIndex.end() != globalLocalIndex.find(indGlo)) ++nbWritten;               
617      }
618
619      localIndexToWriteOnClient.resize(nbWritten); 
620      localIndexToWriteOnServer.resize(nbWritten);
621     
622      {
623        numberWrittenIndexes_ = nbWritten;
624        if (isDataDistributed_)
625        {
626          CContextServer* server = CContext::getCurrent()->server;     
627          MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
628          MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
629          offsetWrittenIndexes_ -= numberWrittenIndexes_;
630        }
631        else
632          totalNumberWrittenIndexes_ = numberWrittenIndexes_;
633      }
634
635      nbWritten = 0; 
636      for (it = itb; it != ite; ++it)
637      {
638        indGlo = it->first;
639        itSrv = globalLocalIndex.find(indGlo);
640        if (itSrve != itSrv)
641        {
642          localIndexToWriteOnServer(nbWritten) = itSrv->second;
643          localIndexToWriteOnClient(nbWritten) = it->second;
644          ++nbWritten;               
645        } 
646      }
647   }
648
649   //---------------------------------------------------------------
650
651   /*
652     Compute the global index and its local index taking account mask and data index.
653     These global indexes will be used to compute the connection of this client (sender) to its servers (receivers)
654     (via function computeConnectedClient)
655     These global indexes also correspond to data sent to servers (if any)
656   */
657   void CGrid::computeClientIndex()
658   {
659     CContext* context = CContext::getCurrent();
660
661     CContextClient* client = context->client;  // Here it's not important which contextClient to recuperate
662     int rank = client->clientRank;
663
664     clientDistribution_ = new CDistributionClient(rank, this);
665     // Get local data index on client
666     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
667     int nbStoreIndex = storeIndex_client.numElements();
668     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
669
670     if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed();
671     else
672     {
673        // Mapping global index received from clients to the storeIndex_client
674        CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
675        CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
676        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
677                                               ite = outGlobalIndexFromClient.end(), it;
678
679        for (it = itb; it != ite; ++it)
680        {
681          int rank = it->first;
682          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
683          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
684          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
685          size_t nbIndex = 0;
686
687          // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
688          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
689          {
690            if (itGloe != globalDataIndex.find(globalIndex(idx)))
691            {
692              ++nbIndex;
693            }
694          }
695
696          if (doGridHaveDataDistributed(client) && (nbIndex != localIndex.numElements()))
697               ERROR("void CGrid::computeClientIndex()",
698                  << "Number of local index on client is different from number of received global index"
699                  << "Rank of sent client " << rank <<"."
700                  << "Number of local index " << nbIndex << ". "
701                  << "Number of received global index " << localIndex.numElements() << ".");
702
703          nbIndex = 0;
704          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
705          {
706            if (itGloe != globalDataIndex.find(globalIndex(idx)))
707            {
708              localIndex(idx) = globalDataIndex[globalIndex(idx)];
709            }
710          }
711        }
712      }
713   }
714
715   /*!
716     Compute connected receivers and indexes to be sent to these receivers.
717   */
718   void CGrid::computeConnectedClients()
719   {
720     CContext* context = CContext::getCurrent();
721     int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size();
722     connectedServerRank_.clear();
723     connectedDataSize_.clear();
724     globalIndexOnServer_.clear();
725     nbSenders.clear();
726
727     for (int p = 0; p < nbSrvPools; ++p)
728     {
729       CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p];
730       int receiverSize = client->serverSize;
731//       connectedServerRank_[client].clear();
732
733       if (connectedServerRank_.find(receiverSize) == connectedServerRank_.end())
734       {
735        if (!doGridHaveDataDistributed(client))
736         {
737            if (client->isServerLeader())
738            {
739              size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
740              const std::list<int>& ranks = client->getRanksServerLeader();
741              for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
742              {
743                connectedServerRank_[receiverSize].push_back(*itRank);
744                connectedDataSize_[receiverSize][*itRank] = ssize;
745              }
746            }
747            return;
748         }
749
750         // Compute mapping between client and server
751         std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
752         CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
753         std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
754                                                                                                    client->clientRank,
755                                                                                                    client->clientSize,
756                                                                                                    axis_domain_order,
757                                                                                                    getDistributedDimension());
758
759         // Even if servers have no index, they must received something from client
760         // We only use several client to send "empty" message to these servers
761         std::list<int> serverZeroIndexLeader;
762         std::list<int> serverZeroIndexNotLeader;
763         CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
764         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
765           *it = serverZeroIndex[*it];
766
767         if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end())
768           computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]);
769
770         const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
771         CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
772         CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
773         itbGlobalMap = globalIndexOnServer_[receiverSize].begin();
774         iteGlobalMap = globalIndexOnServer_[receiverSize].end();
775
776         for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
777         {
778           int serverRank = itGlobalMap->first;
779           int indexSize = itGlobalMap->second.size();
780           const std::vector<size_t>& indexVec = itGlobalMap->second;
781           for (int idx = 0; idx < indexSize; ++idx)
782           {
783              itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
784              if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
785              {
786                if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank))
787                  connectedDataSize_[receiverSize][serverRank] = 1;
788                else
789                  ++connectedDataSize_[receiverSize][serverRank];
790              }
791           }
792         }
793
794         // Connected servers which really have index
795         for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
796           connectedServerRank_[receiverSize].push_back(itGlobalMap->first);
797         }
798
799         // Connected servers which have no index at all
800         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
801           connectedServerRank_[receiverSize].push_back(*it);
802
803         // Even if a client has no index, it must connect to at least one server and
804         // send an "empty" data to this server
805         if (connectedServerRank_[receiverSize].empty())
806          connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);
807
808         nbSenders[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);
809       }
810     }
811   }
812
813   /*!
814     Compute the global index of grid to send to server as well as the connected server of the current client.
815     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
816     their global index. We can have a map of global index of grid and local index that each client holds
817     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
818     of the current client.
819   */
820   void CGrid::computeIndex(void)
821   {
822     CContext* context = CContext::getCurrent();
823     if (isScalarGrid())
824     {
825       computeClientIndexScalarGrid();
826       if (context->hasClient)
827       {
828         computeConnectedClientsScalarGrid();
829       }
830     }
831     else
832     {
833       computeClientIndex();
834       if (context->hasClient)
835       {
836         computeConnectedClients();
837       }
838     }
839   }
840
841   /*!
842      Compute the global of (client) grid to send to server with the global index of each element of grid
843      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
844      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
845      on each element whose size is much smaller than one of whole grid.
846      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
847      \param [in] client contextClient
848      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
849   */
850   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
851                                     const CContextClient* client,
852                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
853   {
854     int serverSize = client->serverSize;
855
856     std::vector<CDomain*> domList = getDomains();
857     std::vector<CAxis*> axisList = getAxis();
858
859     // Some pre-calculations of global index on each element of current grid.
860     int nbElement = axis_domain_order.numElements();
861     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
862     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
863     std::vector<size_t> elementNGlobal(nbElement);
864     elementNGlobal[0] = 1;
865     size_t globalSize = 1;
866     for (int idx = 0; idx < nbElement; ++idx)
867     {
868       elementNGlobal[idx] = globalSize;
869       size_t elementSize;
870       size_t elementGlobalSize = 1;
871       if (2 == axis_domain_order(idx)) // This is domain
872       {
873         elementSize = domList[domainIdx]->i_index.numElements();
874         globalIndexElement[idx].resize(elementSize);
875         for (int jdx = 0; jdx < elementSize; ++jdx)
876         {
877           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
878         }
879         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
880         ++domainIdx;
881       }
882       else if (1 == axis_domain_order(idx))  // This is axis
883       {
884         elementSize = axisList[axisIdx]->index.numElements();
885         globalIndexElement[idx].resize(elementSize);
886         for (int jdx = 0; jdx < elementSize; ++jdx)
887         {
888           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
889         }
890         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
891         ++axisIdx;
892       }
893       else  // Of course, this is scalar
894       {
895         globalIndexElement[idx].resize(1);
896         globalIndexElement[idx](0) = 0;
897         elementGlobalSize = 1;
898       }
899       globalSize *= elementGlobalSize;
900     }
901
902     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
903     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
904     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
905     // Number of temporary distributed global index held by each client for each server
906     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
907     CArray<int,1> nbIndexOnServerTmp(serverSize);
908     for (int idx = 0; idx < nbElement; ++idx)
909     {
910       nbIndexOnServer = 0;
911       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
912       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
913       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
914       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
915       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
916       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
917                                                                    ite = globalIndexElementOnServerMap.end(), it;
918       for (it = itb; it != ite; ++it)
919       {
920         const std::vector<int>& tmp = it->second;
921         nbIndexOnServerTmp = 0;
922         for (int i = 0; i < tmp.size(); ++i)
923         {
924           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
925         }
926         nbIndexOnServer += nbIndexOnServerTmp;
927       }
928
929       for (int i = 0; i < serverSize; ++i)
930       {
931         if (0 != nbIndexOnServer(i))
932         {
933           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
934           elementOnServer[idx][i] = true;
935         }
936       }
937
938     nbIndexOnServer = 0;
939     for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
940     {
941       it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
942       if (it != ite)
943       {
944         const std::vector<int>& tmp = it->second;
945         nbIndexOnServerTmp = 0;
946         for (int i = 0; i < tmp.size(); ++i)
947         {
948           if (0 == nbIndexOnServerTmp(tmp[i]))
949           {
950             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
951             ++nbIndexOnServerTmp(tmp[i]);
952           }
953         }
954         nbIndexOnServer += nbIndexOnServerTmp;
955       }
956     }
957   }
958
959    // Determine server which contain global source index
960    std::vector<bool> intersectedProc(serverSize, true);
961    for (int idx = 0; idx < nbElement; ++idx)
962    {
963      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
964                     intersectedProc.begin(), intersectedProc.begin(),
965                     std::logical_and<bool>());
966    }
967
968    std::vector<int> srcRank;
969    for (int idx = 0; idx < serverSize; ++idx)
970    {
971      if (intersectedProc[idx]) srcRank.push_back(idx);
972    }
973
974    // Compute the global index of grid from global index of each element.
975    for (int i = 0; i < srcRank.size(); ++i)
976    {
977      size_t ssize = 1;
978      int rankSrc = srcRank[i];
979      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
980      std::vector<size_t> currentIndex(nbElement,0);
981      for (int idx = 0; idx < nbElement; ++idx)
982      {
983        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
984        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
985      }
986      globalIndexOnServer[rankSrc].resize(ssize);
987
988      std::vector<int> idxLoop(nbElement,0);
989      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
990      size_t idx = 0;
991      while (idx < ssize)
992      {
993        for (int ind = 0; ind < nbElement; ++ind)
994        {
995          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
996          {
997            idxLoop[ind] = 0;
998            ++idxLoop[ind+1];
999          }
1000
1001          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
1002        }
1003
1004        for (int ind = 0; ind < innnerLoopSize; ++ind)
1005        {
1006          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
1007          size_t globalSrcIndex = 0;
1008          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
1009          {
1010            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
1011          }
1012          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
1013          ++idx;
1014          ++idxLoop[0];
1015        }
1016      }
1017    }
1018   }
1019   //----------------------------------------------------------------
1020
1021   CGrid* CGrid::createGrid(CDomain* domain)
1022   {
1023      std::vector<CDomain*> vecDom(1, domain);
1024      std::vector<CAxis*> vecAxis;
1025
1026      return createGrid(vecDom, vecAxis);
1027   }
1028
1029   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
1030   {
1031      std::vector<CDomain*> vecDom(1, domain);
1032      std::vector<CAxis*> vecAxis(1, axis);
1033
1034      return createGrid(vecDom, vecAxis);
1035   }
1036
1037   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1038                            const CArray<int,1>& axisDomainOrder)
1039   {
1040     std::vector<CScalar*> vecScalar;
1041     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
1042   }
1043
1044   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1045                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1046   {
1047     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
1048   }
1049
1050   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1051                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1052   {
1053      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1054        ERROR("CGrid* CGrid::createGrid(...)",
1055              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1056              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1057
1058      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
1059      grid->setDomainList(domains);
1060      grid->setAxisList(axis);
1061      grid->setScalarList(scalars);
1062
1063      // By default, domains are always the first elements of a grid
1064      if (0 == axisDomainOrder.numElements())
1065      {
1066        int size = domains.size() + axis.size() + scalars.size();
1067        int nb = 0;
1068        grid->axis_domain_order.resize(size);
1069        for (int i = 0; i < size; ++i)
1070        {
1071          if (i < domains.size()) {
1072            grid->axis_domain_order(i) = 2;
1073
1074          }
1075          else if ((scalars.size() < (size-nb)) < size) {
1076            grid->axis_domain_order(i) = 1;
1077          }
1078          else
1079            grid->axis_domain_order(i) = 0;
1080          ++nb;
1081        }
1082      }
1083      else
1084      {
1085        grid->axis_domain_order.resize(axisDomainOrder.numElements());
1086        grid->axis_domain_order = axisDomainOrder;
1087      }
1088
1089      grid->solveDomainAxisRefInheritance(true);
1090
1091      return grid;
1092   }
1093
1094   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
1095   {
1096     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
1097     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
1098     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
1099
1100     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
1101     {
1102       CDomain* domain = CDomain::createDomain();
1103       domain->duplicateAttributes(domainSrcTmp[idx]);
1104       domain->duplicateTransformation(domainSrcTmp[idx]);
1105       domain->solveRefInheritance(true);
1106       domain->solveInheritanceTransformation();
1107       domainSrc.push_back(domain);
1108     }
1109
1110     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
1111     {
1112       CAxis* axis = CAxis::createAxis();
1113       axis->duplicateAttributes(axisSrcTmp[idx]);
1114       axis->duplicateTransformation(axisSrcTmp[idx]);
1115       axis->solveRefInheritance(true);
1116       axis->solveInheritanceTransformation();
1117       axisSrc.push_back(axis);
1118     }
1119
1120     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
1121     {
1122       CScalar* scalar = CScalar::createScalar();
1123       scalar->duplicateAttributes(scalarSrcTmp[idx]);
1124       scalar->duplicateTransformation(scalarSrcTmp[idx]);
1125       scalar->solveRefInheritance(true);
1126       scalar->solveInheritanceTransformation();
1127       scalarSrc.push_back(scalar);
1128     }
1129
1130      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
1131
1132      return grid;
1133   }
1134
1135   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1136                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1137   {
1138      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1139        ERROR("CGrid* CGrid::generateId(...)",
1140              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1141              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1142
1143      std::ostringstream id;
1144
1145      if (domains.empty() && axis.empty() && !scalars.empty())
1146        id << "__scalar_";
1147
1148      if (0 != (domains.size() + axis.size() + scalars.size()))
1149      {
1150        id << "__grid";
1151
1152        if (0 == axisDomainOrder.numElements())
1153        {
1154          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
1155          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
1156          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
1157        }
1158        else
1159        {
1160          size_t iDomain = 0, iAxis = 0, iScalar = 0;
1161          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
1162          {
1163            if (2 == axisDomainOrder(i))
1164              id << "_" << domains[iDomain++]->getId();
1165            else if (1 == axisDomainOrder(i))
1166              id << "_" << axis[iAxis++]->getId();
1167            else
1168              id << "_" << scalars[iScalar++]->getId();
1169          }
1170        }
1171
1172        id << "__";
1173      }
1174
1175      return id.str();
1176   }
1177
1178   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
1179   {
1180     StdString idSrc  = gridSrc->getId();
1181     StdString idDest = gridDest->getId();
1182
1183     std::ostringstream id;
1184     id << idSrc << "__" << idDest;
1185
1186     return id.str();
1187   }
1188
1189   //----------------------------------------------------------------
1190
1191   CDomainGroup* CGrid::getVirtualDomainGroup() const
1192   {
1193     return this->vDomainGroup_;
1194   }
1195
1196   CAxisGroup* CGrid::getVirtualAxisGroup() const
1197   {
1198     return this->vAxisGroup_;
1199   }
1200
1201   CScalarGroup* CGrid::getVirtualScalarGroup() const
1202   {
1203     return this->vScalarGroup_;
1204   }
1205
1206/*
1207   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
1208   {
1209     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
1210     StdSize numElements = stored.numElements();
1211     for (StdSize n = 0; n < numElements; ++n)
1212     {
1213       field[out_i(n)] = stored(n);
1214     }
1215   }
1216
1217   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
1218   {
1219     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
1220     StdSize numElements = stored.numElements();
1221     for (StdSize n = 0; n < numElements; ++n)
1222     {
1223       stored(n) = field[out_i(n)];
1224     }
1225   }
1226
1227   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
1228   {
1229     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
1230     StdSize numElements = stored.numElements();
1231     for (StdSize n = 0; n < numElements; ++n)
1232     {
1233       field[out_i(n)] = stored(n);
1234     }
1235   }
1236*/
1237   //----------------------------------------------------------------
1238
1239   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
1240   {
1241      const StdSize size = storeIndex_client.numElements();
1242
1243      stored.resize(size);
1244      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1245   }
1246
1247   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
1248   {
1249      const StdSize size = storeIndex_client.numElements();
1250
1251      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
1252   }
1253
1254   void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) const
1255   {
1256      const std::vector<int>& localMaskedDataIndex = clientDistribution_->getLocalMaskedDataIndexOnClient();
1257      const int size = localMaskedDataIndex.size();
1258     
1259      for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i];
1260   }
1261
1262  void CGrid::computeClientIndexScalarGrid()
1263  {
1264    CContext* context = CContext::getCurrent();   
1265//    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; // This should be changed soon
1266//    for (int p = 0; p < nbSrvPools; ++p)
1267    {
1268//      CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client)
1269//                                                    : context->client;
1270      CContextClient* client = context->client;
1271
1272      int rank = client->clientRank;
1273
1274      clientDistribution_ = new CDistributionClient(rank, this);
1275
1276      storeIndex_client.resize(1);
1277      storeIndex_client(0) = 0;     
1278
1279      if (0 != serverDistribution_)
1280      {
1281        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
1282                                               ite = outGlobalIndexFromClient.end(), it;
1283        for (it = itb; it != ite; ++it)
1284        {
1285          int rank = it->first;
1286          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1287          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1288          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
1289          if (1 != globalIndex.numElements())
1290            ERROR("void CGrid::computeClientIndexScalarGrid()",
1291              << "Something wrong happened. "
1292              << "Number of received global index on scalar grid should equal to 1" 
1293              << "Number of received global index " << globalIndex.numElements() << ".");
1294
1295          localIndex(0) = globalIndex(0);
1296        }
1297      }
1298    }
1299  }
1300
1301  void CGrid::computeConnectedClientsScalarGrid()
1302  {
1303    CContext* context = CContext::getCurrent();   
1304    int nbSrvPools = (context->clientPrimServer.size()==0) ? 1 : context->clientPrimServer.size();
1305    connectedServerRank_.clear();
1306    connectedDataSize_.clear();
1307    nbSenders.clear();
1308
1309    for (int p = 0; p < nbSrvPools; ++p)
1310    {
1311      CContextClient* client = (context->clientPrimServer.size()==0) ? context->client : context->clientPrimServer[p];
1312      int receiverSize = client->serverSize;
1313
1314//      connectedServerRank_[client].clear();
1315
1316      if (connectedServerRank_.find(receiverSize)==connectedServerRank_.end())
1317      {
1318        if (client->isServerLeader())
1319        {
1320          const std::list<int>& ranks = client->getRanksServerLeader();
1321          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1322          {
1323            int rank = *itRank;
1324            int nb = 1;
1325            connectedServerRank_[receiverSize].push_back(rank);
1326            connectedDataSize_[receiverSize][rank] = nb;
1327            nbSenders[receiverSize][rank] = nb;
1328          }
1329        }
1330        else
1331        {
1332          const std::list<int>& ranks = client->getRanksServerNotLeader();
1333          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1334          {
1335            int rank = *itRank;
1336            int nb = 1;
1337            connectedServerRank_[receiverSize].push_back(rank);
1338            connectedDataSize_[receiverSize][rank] = nb;
1339            nbSenders[receiverSize][rank] = nb;
1340          }
1341        }
1342      }
1343      isDataDistributed_ = false;
1344    }
1345  }
1346
1347  void CGrid::sendIndexScalarGrid()
1348  {
1349    CContext* context = CContext::getCurrent();
1350    storeIndex_toSrv.clear();
1351    std::set<CContextClient*>::iterator it;
1352
1353    for (it=clients.begin(); it!=clients.end(); ++it)
1354    {
1355      CContextClient* client = *it;
1356      int receiverSize = client->serverSize;
1357
1358      CEventClient event(getType(), EVENT_ID_INDEX);
1359      list<CMessage> listMsg;
1360      list<CArray<size_t,1> > listOutIndex;
1361
1362      if (client->isServerLeader())
1363      {
1364        const std::list<int>& ranks = client->getRanksServerLeader();
1365        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1366        {
1367          int rank = *itRank;
1368          int nb = 1;
1369          storeIndex_toSrv[client].insert(std::make_pair(rank, CArray<int,1>(nb)));
1370          listOutIndex.push_back(CArray<size_t,1>(nb));
1371
1372          CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank];
1373          CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1374
1375          for (int k = 0; k < nb; ++k)
1376          {
1377            outGlobalIndexOnServer(k) = 0;
1378            outLocalIndexToServer(k)  = 0;
1379          }
1380
1381          if (context->hasClient && !context->hasServer)
1382            storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1383
1384          listMsg.push_back(CMessage());
1385          listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
1386
1387          event.push(rank, 1, listMsg.back());
1388        }
1389        client->sendEvent(event);
1390      }
1391      else
1392      {
1393        const std::list<int>& ranks = client->getRanksServerNotLeader();
1394        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1395        {
1396          int rank = *itRank;
1397          int nb = 1;         
1398          CArray<int, 1> outLocalIndexToServer(nb);
1399          for (int k = 0; k < nb; ++k)
1400          {
1401            outLocalIndexToServer(k)  = 0;
1402          }
1403
1404          if (context->hasClient && !context->hasServer)
1405            storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1406        }
1407        client->sendEvent(event);
1408      }
1409    }
1410  }
1411
1412  void CGrid::sendIndex(void)
1413  {
1414    CContext* context = CContext::getCurrent();
1415    storeIndex_toSrv.clear();
1416    std::set<CContextClient*>::iterator it;
1417
1418    for (it=clients.begin(); it!=clients.end(); ++it)
1419    {
1420      CContextClient* client = *it;
1421      int receiverSize = client->serverSize;
1422
1423      CEventClient event(getType(), EVENT_ID_INDEX);
1424      int rank;
1425      list<CMessage> listMsg;
1426      list<CArray<size_t,1> > listOutIndex;
1427      const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
1428      CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex,
1429                                                              iteIndex = globalLocalIndexSendToServer.end();
1430      itIndex = itbIndex;                                                             
1431
1432      if (!doGridHaveDataDistributed(client))
1433      {
1434        if (client->isServerLeader())
1435        {
1436          int indexSize = globalLocalIndexSendToServer.size();
1437          CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1438          CArray<int,1> outLocalIndexToServer(indexSize);
1439          for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1440          {
1441            outGlobalIndexOnServer(idx) = itIndex->first;
1442            outLocalIndexToServer(idx) = itIndex->second;
1443          }
1444
1445          const std::list<int>& ranks = client->getRanksServerLeader();
1446          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1447          {
1448            storeIndex_toSrv[client].insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1449            if (context->hasClient && !context->hasServer)
1450              storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1451           
1452            listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1453
1454            listMsg.push_back(CMessage());
1455            listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1456
1457            event.push(*itRank, 1, listMsg.back());
1458          }
1459          client->sendEvent(event);
1460        }
1461        else
1462        {
1463           int indexSize = globalLocalIndexSendToServer.size();
1464           CArray<int,1> outLocalIndexToServer(indexSize);
1465           for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1466           {
1467             outLocalIndexToServer(idx) = itIndex->second;
1468           }
1469
1470           const std::list<int>& ranks = client->getRanksServerNotLeader();
1471           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1472           {
1473             storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1474           }
1475           client->sendEvent(event);
1476         }
1477      }
1478      else
1479      {
1480        CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
1481        itGlobalMap = globalIndexOnServer_[receiverSize].begin();
1482        iteGlobalMap = globalIndexOnServer_[receiverSize].end();
1483
1484        std::map<int,std::vector<int> >localIndexTmp;
1485        std::map<int,std::vector<size_t> > globalIndexTmp;
1486        for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1487        {
1488          int serverRank = itGlobalMap->first;
1489          int indexSize = itGlobalMap->second.size();
1490          const std::vector<size_t>& indexVec = itGlobalMap->second;
1491          for (int idx = 0; idx < indexSize; ++idx)
1492          {
1493            itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
1494            if (iteIndex != itIndex)
1495            {
1496              globalIndexTmp[serverRank].push_back(itIndex->first);
1497              localIndexTmp[serverRank].push_back(itIndex->second);
1498            }
1499          }
1500        }
1501
1502        for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns)
1503        {
1504          rank = connectedServerRank_[receiverSize][ns];
1505          int nb = 0;
1506          if (globalIndexTmp.end() != globalIndexTmp.find(rank))
1507            nb = globalIndexTmp[rank].size();
1508
1509          storeIndex_toSrv[client].insert(make_pair(rank, CArray<int,1>(nb)));
1510          listOutIndex.push_back(CArray<size_t,1>(nb));
1511
1512          CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank];
1513          CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1514
1515          for (int k = 0; k < nb; ++k)
1516          {
1517            outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1518            outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1519          }
1520
1521          storeIndex_fromSrv.insert(make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1522          listMsg.push_back(CMessage());
1523          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1524
1525          event.push(rank, nbSenders[receiverSize][rank], listMsg.back());
1526        }
1527
1528        client->sendEvent(event);
1529      }
1530    }
1531  }
1532
1533  void CGrid::recvIndex(CEventServer& event)
1534  {
1535    string gridId;
1536    vector<int> ranks;
1537    vector<CBufferIn*> buffers;
1538
1539    list<CEventServer::SSubEvent>::iterator it;
1540    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1541    {
1542      ranks.push_back(it->rank);
1543      CBufferIn* buffer = it->buffer;
1544      *buffer >> gridId;
1545      buffers.push_back(buffer);
1546    }
1547    get(gridId)->recvIndex(ranks, buffers);
1548  }
1549
1550  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1551  {
1552    CContext* context = CContext::getCurrent();
1553
1554    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
1555    nbSrvPools = 1;   
1556    nbReadSenders.clear();
1557    for (int p = 0; p < nbSrvPools; ++p)
1558    {
1559      CContextServer* server = (!context->hasClient) ? context->server : context->serverPrimServer[p];
1560      CContextClient* client = context->client;   //(!context->hasClient) ? context->client : context->clientPrimServer[p];
1561     
1562      int idx = 0, numElement = axis_domain_order.numElements();
1563      int ssize = numElement;
1564      std::vector<int> indexMap(numElement);
1565      for (int i = 0; i < numElement; ++i)
1566      {
1567        indexMap[i] = idx;
1568        if (2 == axis_domain_order(i))
1569        {
1570          ++ssize;
1571          idx += 2;
1572        }
1573        else
1574          ++idx;
1575      }
1576
1577      for (int n = 0; n < ranks.size(); n++)
1578      {
1579        int rank = ranks[n];
1580        CBufferIn& buffer = *buffers[n];
1581
1582        buffer >> isDataDistributed_ >> isCompressible_;
1583        size_t dataSize = 0;
1584
1585        if (0 == serverDistribution_)
1586        {
1587          int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1588          std::vector<CDomain*> domainList = getDomains();
1589          std::vector<CAxis*> axisList = getAxis();
1590          std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize), nGlobElement(numElement);
1591          std::vector<CArray<int,1> > globalZoomIndex(numElement);
1592          for (int i = 0; i < numElement; ++i)
1593          {
1594            nGlobElement[i] = globalSize;
1595            if (2 == axis_domain_order(i)) //domain
1596            {
1597              nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin;
1598              nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni;
1599              nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;             
1600              nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1601
1602              nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
1603              nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj;
1604              nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;             
1605              nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1606
1607              {
1608                int count = 0;
1609                globalZoomIndex[i].resize(nZoomSize[indexMap[i]]*nZoomSize[indexMap[i]+1]);
1610                for (int jdx = 0; jdx < nZoomSize[indexMap[i]+1]; ++jdx)
1611                  for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)               
1612                  {
1613                    globalZoomIndex[i](count) = (nZoomBegin[indexMap[i]] + idx) + (nZoomBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
1614                    ++count;
1615                  }
1616              }
1617
1618              ++domainId;
1619            }
1620            else if (1 == axis_domain_order(i)) // axis
1621            {
1622              nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin;
1623              nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_n;
1624              nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;             
1625              nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
1626              if (axisList[axisId]->zoomByIndex())
1627              {
1628                globalZoomIndex[i].reference(axisList[axisId]->zoom_index);               
1629              }
1630              else
1631              {
1632                globalZoomIndex[i].resize(nZoomSize[indexMap[i]]);
1633                for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)
1634                  globalZoomIndex[i](idx) = nZoomBegin[indexMap[i]] + idx;
1635              }
1636
1637              ++axisId;
1638            }
1639            else // scalar
1640            { 
1641              nZoomBegin[indexMap[i]] = 0;
1642              nZoomSize[indexMap[i]]  = 1;
1643              nZoomBeginGlobal[indexMap[i]] = 0;             
1644              nGlob[indexMap[i]] = 1;
1645              globalZoomIndex[i].resize(1);
1646              globalZoomIndex[i](0) = 0;
1647              ++scalarId;
1648            }
1649          }
1650          dataSize = 1;
1651
1652          for (int i = 0; i < nZoomSize.size(); ++i)
1653            dataSize *= nZoomSize[i];
1654          serverDistribution_ = new CDistributionServer(server->intraCommRank, 
1655                                                        globalZoomIndex, axis_domain_order,
1656                                                        nZoomBegin, nZoomSize, nZoomBeginGlobal, nGlob);
1657        }
1658
1659        CArray<size_t,1> outIndex;
1660        buffer >> outIndex;
1661        outGlobalIndexFromClient.insert(std::make_pair(rank, outIndex));       
1662
1663        if (doGridHaveDataDistributed(client))
1664        {}
1665        else
1666        {
1667          // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
1668          // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
1669          dataSize = serverDistribution_->getGridSize();
1670        }
1671        writtenDataSize_ += dataSize;
1672      }
1673
1674
1675      // Compute mask of the current grid
1676      {
1677        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1678        std::vector<CDomain*> domainList = getDomains();
1679        std::vector<CAxis*> axisList = getAxis();
1680        int dimSize = 2 * domainList.size() + axisList.size();
1681        std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize);       
1682        for (int i = 0; i < numElement; ++i)
1683        {         
1684          if (2 == axis_domain_order(i)) //domain
1685          {
1686            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
1687            nSize[indexMap[i]]  = domainList[domainId]->ni;
1688            nBeginGlobal[indexMap[i]] = 0;             
1689            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1690
1691            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
1692            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
1693            nBeginGlobal[indexMap[i] + 1] = 0;             
1694            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1695
1696            ++domainId;
1697          }
1698          else if (1 == axis_domain_order(i)) // axis
1699          {
1700            nBegin[indexMap[i]] = axisList[axisId]->begin;
1701            nSize[indexMap[i]]  = axisList[axisId]->n;
1702            nBeginGlobal[indexMap[i]] = 0;             
1703            nGlob[indexMap[i]] = axisList[axisId]->n_glo;             
1704            ++axisId;
1705          }
1706          else // scalar
1707          { 
1708          }
1709        }
1710       
1711        if (nSize.empty()) // Scalar grid
1712        {
1713          nBegin.push_back(0);
1714          nSize.push_back(1);
1715          nBeginGlobal.push_back(0);             
1716          nGlob.push_back(1); 
1717        }
1718
1719        modifyMaskSize(nSize, false);
1720
1721        // These below codes are reserved for future
1722        CDistributionServer srvDist(server->intraCommRank, nBegin, nSize, nBeginGlobal, nGlob); 
1723        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
1724                                               ite = outGlobalIndexFromClient.end(), it; 
1725        const CDistributionServer::GlobalLocalMap&  globalLocalMask = srvDist.getGlobalLocalIndex();
1726        CDistributionServer::GlobalLocalMap::const_iterator itSrv;
1727        size_t nb = 0;
1728        for (it = itb; it != ite; ++it)
1729        {
1730          CArray<size_t,1>& globalInd = it->second;
1731          for (size_t idx = 0; idx < globalInd.numElements(); ++idx)
1732          {
1733            if (globalLocalMask.end() != globalLocalMask.find(globalInd(idx))) ++nb;
1734          }
1735        }
1736       
1737        CArray<int,1> indexToModify(nb);
1738        nb = 0;   
1739        for (it = itb; it != ite; ++it)
1740        {
1741          CArray<size_t,1>& globalInd = it->second;
1742          for (size_t idx = 0; idx < globalInd.numElements(); ++idx)
1743          {
1744            itSrv = globalLocalMask.find(globalInd(idx));
1745            if (globalLocalMask.end() != itSrv) 
1746            {
1747              indexToModify(nb) = itSrv->second;
1748              ++nb;
1749            }
1750          }
1751        }
1752
1753        modifyMask(indexToModify, true);
1754      }
1755
1756      if (isScalarGrid()) return;
1757
1758      nbReadSenders[client] = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1759    }
1760  }
1761
1762  /*
1763     Compute on the fly the global dimension of a grid with its elements
1764     \param[in/out] globalDim global dimension of grid
1765     \param[in] domains list of its domains
1766     \param[in] axiss list of its axis
1767     \param[in] scalars list of its scalars
1768     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1769     \return The dimension of which we do distribution (often for server)
1770  */
1771  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1772                                        const std::vector<CDomain*> domains,
1773                                        const std::vector<CAxis*> axis,
1774                                        const std::vector<CScalar*> scalars,
1775                                        const CArray<int,1>& axisDomainOrder)
1776  {
1777    globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1778    int positionDimensionDistributed = 1;
1779    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1780    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1781    {
1782      if (2 == axisDomainOrder(i))
1783      {
1784        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1785        {
1786          positionDimensionDistributed = idx;
1787        }
1788        else
1789        {
1790          positionDimensionDistributed = idx +1;
1791        }
1792
1793        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
1794        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
1795
1796        ++idxDomain;
1797        idx += 2;
1798      }
1799      else if (1 == axisDomainOrder(i))
1800      {
1801        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
1802        ++idxAxis;
1803        ++idx;
1804      }
1805      else
1806      {
1807        globalDim[idx] = 1;
1808        ++idxScalar;
1809        ++idx;
1810      }
1811    }
1812
1813    return positionDimensionDistributed;
1814  }
1815
1816  // Retrieve the global dimension of grid
1817  std::vector<int> CGrid::getGlobalDimension()
1818  {
1819    std::vector<int> globalDim;
1820    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
1821
1822    return globalDim;
1823  }
1824
1825  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
1826  int CGrid::getDistributedDimension()
1827  {
1828    std::vector<int> globalDim;
1829    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
1830  }
1831
1832  bool CGrid::isScalarGrid() const
1833  {
1834    return (axisList_.empty() && domList_.empty());
1835  }
1836
1837  /*!
1838    Verify whether one server need to write data
1839    There are some cases on which one server has nodata to write. For example, when we
1840    just only want to zoom on a domain.
1841  */
1842  bool CGrid::doGridHaveDataToWrite()
1843  {
1844     return (0 != writtenDataSize_);
1845  }
1846
1847  /*!
1848    Return size of data which is written on each server
1849    Whatever dimension of a grid, data which are written on server must be presented as
1850    an one dimension array.
1851    \return size of data written on server
1852  */
1853  size_t CGrid::getWrittenDataSize() const
1854  {
1855    return writtenDataSize_;
1856  }
1857
1858  /*!
1859    Returns the number of indexes written by each server.
1860    \return the number of indexes written by each server
1861  */
1862  int CGrid::getNumberWrittenIndexes() const
1863  {
1864    return numberWrittenIndexes_;
1865  }
1866
1867  /*!
1868    Returns the total number of indexes written by the servers.
1869    \return the total number of indexes written by the servers
1870  */
1871  int CGrid::getTotalNumberWrittenIndexes() const
1872  {
1873    return totalNumberWrittenIndexes_;
1874  }
1875
1876  /*!
1877    Returns the offset of indexes written by each server.
1878    \return the offset of indexes written by each server
1879  */
1880  int CGrid::getOffsetWrittenIndexes() const
1881  {
1882    return offsetWrittenIndexes_;
1883  }
1884
1885  CDistributionServer* CGrid::getDistributionServer()
1886  {
1887    return serverDistribution_;
1888  }
1889
1890  CDistributionClient* CGrid::getDistributionClient()
1891  {
1892    return clientDistribution_;
1893  }
1894
1895  bool CGrid::doGridHaveDataDistributed(CContextClient* client)
1896  {
1897    if (isScalarGrid()) return false;
1898    else if (0 != client)
1899    {
1900      return  (isDataDistributed_ ||  (1 != client->clientSize) || (1 != client->serverSize));
1901    }
1902    else
1903      return isDataDistributed_;   
1904  }
1905
1906   /*!
1907   \brief Dispatch event received from client
1908      Whenever a message is received in buffer of server, it will be processed depending on
1909   its event type. A new event type should be added in the switch list to make sure
1910   it processed on server side.
1911   \param [in] event: Received message
1912   */
1913  bool CGrid::dispatchEvent(CEventServer& event)
1914  {
1915
1916    if (SuperClass::dispatchEvent(event)) return true;
1917    else
1918    {
1919      switch(event.type)
1920      {
1921        case EVENT_ID_INDEX :
1922          recvIndex(event);
1923          return true;
1924          break;
1925
1926         case EVENT_ID_ADD_DOMAIN :
1927           recvAddDomain(event);
1928           return true;
1929           break;
1930
1931         case EVENT_ID_ADD_AXIS :
1932           recvAddAxis(event);
1933           return true;
1934           break;
1935
1936         case EVENT_ID_ADD_SCALAR :
1937           recvAddScalar(event);
1938           return true;
1939           break;
1940        default :
1941          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1942                << "Unknown Event");
1943          return false;
1944      }
1945    }
1946  }
1947
1948   ///---------------------------------------------------------------
1949
1950   CDomain* CGrid::addDomain(const std::string& id)
1951   {
1952     order_.push_back(2);
1953     axis_domain_order.resize(order_.size());
1954     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1955     return vDomainGroup_->createChild(id);
1956   }
1957
1958   CAxis* CGrid::addAxis(const std::string& id)
1959   {
1960     order_.push_back(1);
1961     axis_domain_order.resize(order_.size());
1962     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1963     return vAxisGroup_->createChild(id);
1964   }
1965
1966   CScalar* CGrid::addScalar(const std::string& id)
1967   {
1968     order_.push_back(0);
1969     axis_domain_order.resize(order_.size());
1970     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1971     return vScalarGroup_->createChild(id);
1972   }
1973
1974   //! Change virtual field group to a new one
1975   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1976   {
1977      this->vDomainGroup_ = newVDomainGroup;
1978   }
1979
1980   //! Change virtual variable group to new one
1981   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1982   {
1983      this->vAxisGroup_ = newVAxisGroup;
1984   }
1985
1986   //! Change virtual variable group to new one
1987   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
1988   {
1989      this->vScalarGroup_ = newVScalarGroup;
1990   }
1991
1992   /*!
1993   \brief Send a message to create a domain on server side
1994   \param[in] id String identity of domain that will be created on server
1995   */
1996   void CGrid::sendAddDomain(const string& id)
1997   {
1998      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN);
1999   }
2000
2001   /*!
2002   \brief Send a message to create an axis on server side
2003   \param[in] id String identity of axis that will be created on server
2004   */
2005   void CGrid::sendAddAxis(const string& id)
2006   {
2007      sendAddItem(id, (int)EVENT_ID_ADD_AXIS);
2008   }
2009
2010   /*!
2011   \brief Send a message to create a scalar on server side
2012   \param[in] id String identity of scalar that will be created on server
2013   */
2014   void CGrid::sendAddScalar(const string& id)
2015   {
2016      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR);
2017   }
2018
2019   /*!
2020   \brief Receive a message annoucing the creation of a domain on server side
2021   \param[in] event Received event
2022   */
2023   void CGrid::recvAddDomain(CEventServer& event)
2024   {
2025
2026      CBufferIn* buffer = event.subEvents.begin()->buffer;
2027      string id;
2028      *buffer >> id;
2029      get(id)->recvAddDomain(*buffer);
2030   }
2031
2032   /*!
2033   \brief Receive a message annoucing the creation of a domain on server side
2034   \param[in] buffer Buffer containing message
2035   */
2036   void CGrid::recvAddDomain(CBufferIn& buffer)
2037   {
2038      string id;
2039      buffer >> id;
2040      addDomain(id);
2041   }
2042
2043   /*!
2044   \brief Receive a message annoucing the creation of an axis on server side
2045   \param[in] event Received event
2046   */
2047   void CGrid::recvAddAxis(CEventServer& event)
2048   {
2049
2050      CBufferIn* buffer = event.subEvents.begin()->buffer;
2051      string id;
2052      *buffer >> id;
2053      get(id)->recvAddAxis(*buffer);
2054   }
2055
2056   /*!
2057   \brief Receive a message annoucing the creation of an axis on server side
2058   \param[in] buffer Buffer containing message
2059   */
2060   void CGrid::recvAddAxis(CBufferIn& buffer)
2061   {
2062      string id;
2063      buffer >> id;
2064      addAxis(id);
2065   }
2066
2067   /*!
2068   \brief Receive a message annoucing the creation of an scalar on server side
2069   \param[in] event Received event
2070   */
2071   void CGrid::recvAddScalar(CEventServer& event)
2072   {
2073
2074      CBufferIn* buffer = event.subEvents.begin()->buffer;
2075      string id;
2076      *buffer >> id;
2077      get(id)->recvAddScalar(*buffer);
2078   }
2079
2080   /*!
2081   \brief Receive a message annoucing the creation of an scalar on server side
2082   \param[in] buffer Buffer containing message
2083   */
2084   void CGrid::recvAddScalar(CBufferIn& buffer)
2085   {
2086      string id;
2087      buffer >> id;
2088      addScalar(id);
2089   }
2090
2091  /*!
2092  \brief Solve domain and axis references
2093  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
2094  all attributes from their parents, they should be processed with this function
2095  \param[in] apply inherit all attributes of parents (true)
2096  */
2097  void CGrid::solveDomainAxisRefInheritance(bool apply)
2098  {
2099    CContext* context = CContext::getCurrent();
2100    unsigned int vecSize, i;
2101    std::vector<StdString>::iterator it, itE;
2102    setDomainList();
2103    it = domList_.begin(); itE = domList_.end();
2104    for (; it != itE; ++it)
2105    {
2106      CDomain* pDom = CDomain::get(*it);
2107      if (context->hasClient && !context->hasServer)     
2108      {
2109        pDom->solveRefInheritance(apply);
2110        pDom->solveInheritanceTransformation();
2111      }
2112    }
2113
2114    setAxisList();
2115    it = axisList_.begin(); itE = axisList_.end();
2116    for (; it != itE; ++it)
2117    {
2118      CAxis* pAxis = CAxis::get(*it);
2119      if (context->hasClient && !context->hasServer)
2120      {
2121        pAxis->solveRefInheritance(apply);
2122        pAxis->solveInheritanceTransformation();
2123      }
2124    }
2125
2126    setScalarList();
2127    it = scalarList_.begin(); itE = scalarList_.end();
2128    for (; it != itE; ++it)
2129    {
2130      CScalar* pScalar = CScalar::get(*it);
2131      if (context->hasClient && !context->hasServer)
2132      {
2133        pScalar->solveRefInheritance(apply);
2134        pScalar->solveInheritanceTransformation();
2135      }
2136    }
2137  }
2138
2139  bool CGrid::isTransformed()
2140  {
2141    return isTransformed_;
2142  }
2143
2144  void CGrid::setTransformed()
2145  {
2146    isTransformed_ = true;
2147  }
2148
2149  CGridTransformation* CGrid::getTransformations()
2150  {
2151    return transformations_;
2152  }
2153
2154  void CGrid::addTransGridSource(CGrid* gridSrc)
2155  {
2156    if (gridSrc_.end() == gridSrc_.find(gridSrc))
2157      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
2158  }
2159
2160  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
2161  {
2162    return gridSrc_;
2163  }
2164
2165  /*!
2166     Complete all the necessary (and lacking) attributes of a grid
2167     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
2168  */
2169  void CGrid::completeGrid(CGrid* transformGridSrc)
2170  {
2171    if (0 != transformGridSrc)
2172    {
2173      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2174      {
2175        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
2176             << "Two grids have different number of elements. " << std::endl
2177             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2178             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2179      }
2180    }
2181
2182    if (isGenerated()) return;
2183    setGenerated();
2184
2185    CGridGenerate gridGenerate(this, transformGridSrc);
2186    gridGenerate.completeGrid();
2187  }
2188
2189  bool CGrid::isGenerated()
2190  {
2191    return isGenerated_;
2192  }
2193
2194  void CGrid::setGenerated()
2195  {
2196    isGenerated_ = true;
2197  }
2198
2199  void CGrid::transformGrid(CGrid* transformGridSrc)
2200  {
2201    if (!transformGridSrc)
2202      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2203            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
2204
2205    if (isTransformed()) return;
2206    setTransformed();
2207    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
2208    {
2209      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
2210           << "Two grids have different number of elements. " << std::endl
2211           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
2212           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
2213    }
2214    else
2215    {
2216    }
2217
2218    transformations_ = new CGridTransformation(this, transformGridSrc);
2219    transformations_->computeAll();
2220    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
2221
2222    // Ok, now need to compute index of grid source
2223    transformGridSrc->checkMaskIndex(false);
2224  }
2225
2226  bool CGrid::hasTransform()
2227  {
2228    if (hasTransform_) return hasTransform_;
2229
2230    std::vector<CDomain*> domList = getDomains();
2231    std::vector<CAxis*> axisList = getAxis();
2232    std::vector<CScalar*> scalarList = getScalars();
2233
2234    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
2235    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
2236    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
2237
2238    return hasTransform_;
2239  }
2240
2241  /*!
2242  \brief Get the list of domain pointers
2243  \return list of domain pointers
2244  */
2245  std::vector<CDomain*> CGrid::getDomains()
2246  {
2247    std::vector<CDomain*> domList;
2248    if (!domList_.empty())
2249    {
2250      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
2251    }
2252    return domList;
2253  }
2254
2255  /*!
2256  \brief Get the list of  axis pointers
2257  \return list of axis pointers
2258  */
2259  std::vector<CAxis*> CGrid::getAxis()
2260  {
2261    std::vector<CAxis*> aList;
2262    if (!axisList_.empty())
2263      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
2264
2265    return aList;
2266  }
2267
2268  /*!
2269  \brief Get the list of  axis pointers
2270  \return list of axis pointers
2271  */
2272  std::vector<CScalar*> CGrid::getScalars()
2273  {
2274    std::vector<CScalar*> sList;
2275    if (!scalarList_.empty())
2276      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
2277
2278    return sList;
2279  }
2280
2281  /*!
2282  \brief Get domain pointer with index
2283  \return domain pointer
2284  */
2285  CDomain* CGrid::getDomain(int domainIndex)
2286  {
2287    std::vector<CDomain*> domainListP = this->getDomains();
2288    if (domainListP.empty())
2289    {
2290      ERROR("CGrid::getDomain(int domainIndex)",
2291            << "No domain associated to this grid. " << std::endl
2292            << "Grid id = " << this->getId());
2293    }
2294
2295    if (domainIndex >= domainListP.size() || (domainIndex < 0))
2296      ERROR("CGrid::getDomain(int domainIndex)",
2297            << "Domain with the index doesn't exist " << std::endl
2298            << "Grid id = " << this->getId() << std::endl
2299            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
2300
2301    return domainListP[domainIndex];
2302  }
2303
2304  /*!
2305  \brief Get the axis pointer with index
2306  \return axis pointer
2307  */
2308  CAxis* CGrid::getAxis(int axisIndex)
2309  {
2310    std::vector<CAxis*> axisListP = this->getAxis();
2311    if (axisListP.empty())
2312    {
2313      ERROR("CGrid::getDomain(int axisIndex)",
2314            << "No axis associated to this grid. " << std::endl
2315            << "Grid id = " << this->getId());
2316    }
2317
2318    if (axisIndex >= axisListP.size() || (axisIndex < 0))
2319      ERROR("CGrid::getDomain(int axisIndex)",
2320            << "Domain with the index doesn't exist " << std::endl
2321            << "Grid id = " << this->getId() << std::endl
2322            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
2323
2324    return axisListP[axisIndex];
2325  }
2326
2327  /*!
2328  \brief Get the a scalar pointer
2329  \return scalar pointer
2330  */
2331  CScalar* CGrid::getScalar(int scalarIndex)
2332  {
2333    std::vector<CScalar*> scalarListP = this->getScalars();
2334    if (scalarListP.empty())
2335    {
2336      ERROR("CGrid::getScalar(int scalarIndex)",
2337            << "No scalar associated to this grid. " << std::endl
2338            << "Grid id = " << this->getId());
2339    }
2340
2341    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
2342      ERROR("CGrid::getScalar(int scalarIndex)",
2343            << "Scalar with the index doesn't exist " << std::endl
2344            << "Grid id = " << this->getId() << std::endl
2345            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
2346
2347    return scalarListP[scalarIndex];
2348  }
2349
2350  /*!
2351  \brief Set domain(s) of a grid from a list
2352  \param[in] domains list of domains
2353  */
2354  void CGrid::setDomainList(const std::vector<CDomain*> domains)
2355  {
2356    if (isDomListSet) return;
2357    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2358    if (!domains.empty() && domList.empty())
2359    {
2360      for (int i = 0; i < domains.size(); ++i)
2361        this->getVirtualDomainGroup()->addChild(domains[i]);
2362      domList = this->getVirtualDomainGroup()->getAllChildren();
2363    }
2364
2365    if (!domList.empty())
2366    {
2367      int sizeDom = domList.size();
2368      domList_.resize(sizeDom);
2369      for (int i = 0; i < sizeDom; ++i)
2370      {
2371        domList_[i] = domList[i]->getId();
2372      }
2373      isDomListSet = true;
2374    }
2375
2376  }
2377
2378  /*!
2379  \brief Set axis(s) of a grid from a list
2380  \param[in] axis list of axis
2381  */
2382  void CGrid::setAxisList(const std::vector<CAxis*> axis)
2383  {
2384    if (isAxisListSet) return;
2385    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2386    if (!axis.empty() && aList.empty())
2387    {
2388      for (int i = 0; i < axis.size(); ++i)
2389        this->getVirtualAxisGroup()->addChild(axis[i]);
2390      aList = this->getVirtualAxisGroup()->getAllChildren();
2391    }
2392
2393    if (!aList.empty())
2394    {
2395      int sizeAxis = aList.size();
2396      axisList_.resize(sizeAxis);
2397      for (int i = 0; i < sizeAxis; ++i)
2398      {
2399        axisList_[i] = aList[i]->getId();
2400      }
2401      isAxisListSet = true;
2402    }
2403  }
2404
2405  /*!
2406  \brief Set scalar(s) of a grid from a list
2407  \param[in] scalars list of scalars
2408  */
2409  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
2410  {
2411    if (isScalarListSet) return;
2412    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2413    if (!scalars.empty() && sList.empty())
2414    {
2415      for (int i = 0; i < scalars.size(); ++i)
2416        this->getVirtualScalarGroup()->addChild(scalars[i]);
2417      sList = this->getVirtualScalarGroup()->getAllChildren();
2418    }
2419
2420    if (!sList.empty())
2421    {
2422      int sizeScalar = sList.size();
2423      scalarList_.resize(sizeScalar);
2424      for (int i = 0; i < sizeScalar; ++i)
2425      {
2426        scalarList_[i] = sList[i]->getId();
2427      }
2428      isScalarListSet = true;
2429    }
2430  }
2431
2432  /*!
2433  \brief Get list of id of domains
2434  \return id list of domains
2435  */
2436  std::vector<StdString> CGrid::getDomainList()
2437  {
2438    setDomainList();
2439    return domList_;
2440  }
2441
2442  /*!
2443  \brief Get list of id of axis
2444  \return id list of axis
2445  */
2446  std::vector<StdString> CGrid::getAxisList()
2447  {
2448    setAxisList();
2449    return axisList_;
2450  }
2451
2452  /*!
2453  \brief Get list of id of scalar
2454  \return id list of scalar
2455  */
2456  std::vector<StdString> CGrid::getScalarList()
2457  {
2458    setScalarList();
2459    return scalarList_;
2460  }
2461
2462  /*!
2463    Send all attributes of domains from client to server
2464  */
2465  void CGrid::sendAllDomains()
2466  {
2467    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
2468    int dSize = domList.size();
2469    for (int i = 0; i < dSize; ++i)
2470    {
2471      sendAddDomain(domList[i]->getId());
2472      domList[i]->sendAllAttributesToServer();
2473    }
2474  }
2475
2476  /*!
2477    Send all attributes of axis from client to server
2478  */
2479  void CGrid::sendAllAxis()
2480  {
2481    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
2482    int aSize = aList.size();
2483
2484    for (int i = 0; i < aSize; ++i)
2485    {
2486      sendAddAxis(aList[i]->getId());
2487      aList[i]->sendAllAttributesToServer();
2488    }
2489  }
2490
2491  /*!
2492    Send all attributes of scalars from client to server
2493  */
2494  void CGrid::sendAllScalars()
2495  {
2496    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
2497    int sSize = sList.size();
2498
2499    for (int i = 0; i < sSize; ++i)
2500    {
2501      sendAddScalar(sList[i]->getId());
2502      sList[i]->sendAllAttributesToServer();
2503    }
2504  }
2505
2506  void CGrid::setContextClient(CContextClient* contextClient)
2507  {
2508    clients.insert(contextClient);
2509  }
2510
2511  /*!
2512    Parse a grid, for now, it contains only domain, axis and scalar
2513  */
2514  void CGrid::parse(xml::CXMLNode& node)
2515  {
2516    SuperClass::parse(node);
2517
2518    if (node.goToChildElement())
2519    {
2520      StdString domainName("domain");
2521      StdString axisName("axis");
2522      StdString scalarName("scalar");
2523      do
2524      {
2525        if (node.getElementName() == domainName) {
2526          order_.push_back(2);
2527          this->getVirtualDomainGroup()->parseChild(node);
2528        }
2529        if (node.getElementName() == axisName) {
2530          order_.push_back(1);
2531          this->getVirtualAxisGroup()->parseChild(node);
2532        }
2533        if (node.getElementName() == scalarName) {
2534          order_.push_back(0);
2535          this->getVirtualScalarGroup()->parseChild(node);
2536        }
2537      } while (node.goToNextElement());
2538      node.goToParentElement();
2539    }
2540
2541    if (!order_.empty())
2542    {
2543      int sizeOrd = order_.size();
2544      axis_domain_order.resize(sizeOrd);
2545      for (int i = 0; i < sizeOrd; ++i)
2546      {
2547        axis_domain_order(i) = order_[i];
2548      }
2549    }
2550
2551    setDomainList();
2552    setAxisList();
2553    setScalarList();
2554   }
2555} // namespace xios
Note: See TracBrowser for help on using the repository browser.