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

Last change on this file since 1372 was 1371, checked in by oabramkina, 6 years ago

Fixing a bug in buffer evaluation: previously axis attributes were not evaluated correctly.

  • 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.8 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20#include "server.hpp"
21
22namespace xios {
23
24   /// ////////////////////// Dfinitions ////////////////////// ///
25
26   CGrid::CGrid(void)
27      : CObjectTemplate<CGrid>(), CGridAttributes()
28      , isChecked(false), isDomainAxisChecked(false)
29      , vDomainGroup_(), domList_(), isDomListSet(false)
30      , vAxisGroup_(), axisList_(), isAxisListSet(false)
31      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
32      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
33      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
34      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
35          , isDataDistributed_(true), isCompressible_(false)
36      , transformations_(0), isTransformed_(false)
37      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
38      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
39      , computedWrittenIndex_(false)
40      , clients()
41   {
42     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
43     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
44     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
45   }
46
47   CGrid::CGrid(const StdString& id)
48      : CObjectTemplate<CGrid>(id), CGridAttributes()
49      , isChecked(false), isDomainAxisChecked(false)
50      , vDomainGroup_(), domList_(), isDomListSet(false)
51      , vAxisGroup_(), axisList_(), isAxisListSet(false)
52      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
53      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
54      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
55      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
56          , isDataDistributed_(true), isCompressible_(false)
57      , transformations_(0), isTransformed_(false)
58      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
59      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
60      , computedWrittenIndex_(false)
61      , clients()
62   {
63     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
64     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
65     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
66   }
67
68   CGrid::~CGrid(void)
69   {
70    if (0 != clientDistribution_) delete clientDistribution_;
71    if (0 != serverDistribution_) delete serverDistribution_;
72    if (0 != clientServerMap_) delete clientServerMap_;
73    if (0 != transformations_) delete transformations_;
74   }
75
76   ///---------------------------------------------------------------
77
78   StdString CGrid::GetName(void)    { return StdString("grid"); }
79   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
80   ENodeType CGrid::GetType(void)    { return eGrid; }
81
82
83   StdSize CGrid::getDimension(void)
84   {
85      return getGlobalDimension().size();
86   }
87
88   //---------------------------------------------------------------
89
90   StdSize CGrid::getDataSize(void) const
91   {
92     StdSize retvalue = 1;
93     if (!isScalarGrid())
94     {
95       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
96       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];       
97     }
98     return retvalue;
99   }
100
101   /*!
102    * Compute the minimum buffer size required to send the attributes to the server(s).
103    *
104    * \return A map associating the server rank with its minimum buffer size.
105    * TODO: Refactor code
106    */
107   std::map<int, StdSize> CGrid::getAttributesBufferSize(CContextClient* client, bool bufferForWriting)
108   {
109     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
110
111     // The grid indexes require a similar size as the actual data
112     std::map<int, StdSize> dataSizes = getDataBufferSize(client, "", bufferForWriting);
113     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
114     for (it = dataSizes.begin(); it != itE; ++it)
115     {
116       it->second += 2 * sizeof(bool);
117       if (it->second > attributesSizes[it->first])
118         attributesSizes[it->first] = it->second;
119     }
120     
121     // Account for the axis attributes
122     std::vector<CAxis*> axisList = getAxis();
123     for (size_t i = 0; i < axisList.size(); ++i)
124     {
125       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client, getGlobalDimension(),axisPositionInGrid_[i]);
126       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
127       {
128         it->second += 2 * sizeof(bool);
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         it->second += 2 * sizeof(bool);
142         if (it->second > attributesSizes[it->first])
143           attributesSizes[it->first] = it->second;
144       }
145     }
146
147     return attributesSizes;
148  }
149
150   /*!
151    * Compute the minimum buffer size required to send the data.
152    * \param client contextClient used to determine the size of connected receivers
153    * \param id the id used to tag the data
154    * \param bufferForWriting flag indicating if a buffer is used to send data for writing
155    * \return A map associating the sender rank with its minimum buffer size.
156    */
157   std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/, bool bufferForWriting /*= "false"*/)
158   {     
159     // The record index is sometimes sent along with the data but we always
160     // include it in the size calculation for the sake of simplicity
161     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() 
162                                                       + 2 * sizeof(size_t) 
163                                                       + sizeof(size_t);
164
165     std::map<int, StdSize> dataSizes;
166     int receiverSize = client->serverSize;
167     std::map<int,size_t>& dataSizeMap = bufferForWriting ? connectedDataSize_[receiverSize]: connectedDataSizeRead_;
168     std::vector<int>& connectedServerRanks = bufferForWriting ? connectedServerRank_[receiverSize] : connectedServerRankRead_;
169
170     std::map<int, size_t>::const_iterator itEnd = dataSizeMap.end();
171     for (size_t k = 0; k < connectedServerRanks.size(); ++k)
172     {
173       int rank = connectedServerRanks[k];
174       std::map<int, size_t>::const_iterator it = dataSizeMap.find(rank);
175       size_t count = (it != itEnd) ? it->second : 0;
176
177       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
178     }
179
180     return dataSizes;
181   }
182
183   size_t CGrid::getGlobalWrittenSize(void)
184   {
185         std::vector<CDomain*> domainP = this->getDomains();
186     std::vector<CAxis*> axisP = this->getAxis();
187     
188     size_t globalGridSize=1 ;
189     for (std::vector<CDomain*>::iterator it=domainP.begin(); it!=domainP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
190     for (std::vector<CAxis*>::iterator it=axisP.begin(); it!=axisP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
191     return globalGridSize ;
192   }
193   
194   
195   void CGrid::checkAttributesAfterTransformation()
196   {
197      setAxisList();
198      std::vector<CAxis*> axisListP = this->getAxis();
199      if (!axisListP.empty())
200      {
201        int idx = 0;
202        axisPositionInGrid_.resize(0);
203        for (int i = 0; i < axis_domain_order.numElements(); ++i)
204        {
205          int elementDimension = axis_domain_order(i);
206          if (1 == elementDimension)
207          {
208            axisPositionInGrid_.push_back(idx);
209            ++idx;
210          }
211          else if (2 == elementDimension) idx += 2;
212        }
213
214        for (int i = 0; i < axisListP.size(); ++i)
215        {
216          axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(),axisPositionInGrid_[i]);
217        }
218      }
219
220      setDomainList();
221      std::vector<CDomain*> domListP = this->getDomains();
222      if (!domListP.empty())
223      {
224        for (int i = 0; i < domListP.size(); ++i)
225        {
226          domListP[i]->checkAttributesOnClientAfterTransformation();
227        }
228      }
229   }
230
231   //---------------------------------------------------------------
232
233   /*!
234    * Test whether the data defined on the grid can be outputted in a compressed way.
235    *
236    * \return true if and only if a mask was defined for this grid
237    */
238   bool CGrid::isCompressible(void) const
239   {
240      return isCompressible_;
241   }
242
243   //---------------------------------------------------------------
244
245   void CGrid::addRelFileCompressed(const StdString& filename)
246   {
247      this->relFilesCompressed.insert(filename);
248   }
249
250   bool CGrid::isWrittenCompressed(const StdString& filename) const
251   {
252      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
253   }
254
255   //---------------------------------------------------------------
256   /*
257     Find all reference of grid's components and inherite attributes if necessary
258   */
259   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
260   {
261     if (this->isDomainAxisChecked) return;
262
263     this->solveScalarRef(areAttributesChecked);
264     this->solveAxisRef(areAttributesChecked);
265     this->solveDomainRef(areAttributesChecked);     
266     this->isDomainAxisChecked = areAttributesChecked;
267   }
268
269   /*
270     Go up hierachy reference and fill in the base reference with attributes of the children
271     This function should be only used after reading component's attributes from file
272   */
273   void CGrid::solveDomainAxisBaseRef()
274   {
275     if (this->hasDomainAxisBaseRef_) return;
276     // Account for the scalar attributes
277     std::vector<CScalar*> scalarList = getScalars();
278     for (size_t i = 0; i < scalarList.size(); ++i)
279     {
280       scalarList[i]->setAttributesReference();
281     }
282
283     // Account for the axis attributes
284     std::vector<CAxis*> axisList = getAxis();
285     for (size_t i = 0; i < axisList.size(); ++i)
286     {
287       axisList[i]->setAttributesReference();
288     }
289
290     // Account for the domain attributes
291     std::vector<CDomain*> domList = getDomains();
292     for (size_t i = 0; i < domList.size(); ++i)
293     {
294       domList[i]->setAttributesReference();
295     }
296
297     this->hasDomainAxisBaseRef_ = true;
298   }
299
300   void CGrid::checkEligibilityForCompressedOutput()
301   {
302     // We don't check if the mask is valid here, just if a mask has been defined at this point.
303     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
304   }
305
306   void CGrid::checkMaskIndex(bool doSendingIndex)
307   {
308     CContext* context = CContext::getCurrent();
309     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;   
310     nbSrvPools = 1; 
311     for (int p = 0; p < nbSrvPools; ++p)
312     {   
313       if (context->hasClient && this->isChecked && doSendingIndex && !isIndexSent) 
314       { 
315         if (isScalarGrid())
316           sendIndexScalarGrid();
317         else
318           sendIndex();
319         this->isIndexSent = true; 
320       }
321
322       // Not sure about this
323       //if (!(this->hasTransform() && !this->isTransformed()))
324       // this->isChecked = true;
325       //return;
326     }
327   
328     if (this->isChecked) return;
329     this->checkAttributesAfterTransformation();
330
331     // TODO: Transfer grid attributes
332     //if (!context->hasClient && context->hasServer) this->createMask();
333     this->computeIndex();
334
335     if (!(this->hasTransform() && !this->isTransformed()))
336      this->isChecked = true;
337
338     if (!(this->hasTransform() && (!this->isGenerated())))
339      this->isChecked = true;
340   }
341
342   /*
343     Create mask of grid from mask of its components
344   */
345   void CGrid::createMask(void)
346   {
347      using namespace std;
348      std::vector<CDomain*> domainP = this->getDomains();
349      std::vector<CAxis*> axisP = this->getAxis();
350      int dim = domainP.size() * 2 + axisP.size();
351
352      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
353      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask);
354      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
355      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
356
357      switch (dim) {
358        case 1:
359          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
360          break;
361        case 2:
362          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
363          break;
364        case 3:
365          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
366          break;
367        case 4:
368          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true);
369          break;
370        case 5:
371          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true);
372          break;
373        case 6:
374          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true);
375          break;
376        case 7:
377          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true);
378          break;
379        default:
380          break;
381      }
382   }
383
384   /*
385     Check validity of grid's mask by using the masks of its components
386   */
387   void CGrid::checkMask(void)
388   {
389      using namespace std;
390      std::vector<CDomain*> domainP = this->getDomains();
391      std::vector<CAxis*> axisP = this->getAxis();
392      int dim = domainP.size() * 2 + axisP.size();
393
394      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
395      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask);
396      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
397      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
398
399      switch (dim) {
400        case 1:
401          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
402          break;
403        case 2:
404          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
405          break;
406        case 3:
407          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
408          break;
409        case 4:
410          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order);
411          break;
412        case 5:
413          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order);
414          break;
415        case 6:
416          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order);
417          break;
418        case 7:
419          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order);
420          break;
421        default:
422          break;
423      }
424   }
425
426   /*
427     Modify value of mask in a certain index
428     This function can be used to correct the mask of grid after being constructed with createMask
429     \param [in] indexToModify
430     \param [in] modifyValue
431   */
432   void CGrid::modifyMask(const CArray<int,1>& indexToModify, bool modifyValue)
433   {
434      using namespace std;
435      std::vector<CDomain*> domainP = this->getDomains();
436      std::vector<CAxis*> axisP = this->getAxis();
437      int dim = domainP.size() * 2 + axisP.size();
438
439      switch (dim) {
440        case 0:
441          modifyGridMask(mask_0d, indexToModify, modifyValue);
442          break;
443        case 1:
444          modifyGridMask(mask_1d, indexToModify, modifyValue);
445          break;
446        case 2:
447          modifyGridMask(mask_2d, indexToModify, modifyValue);
448          break;
449        case 3:
450          modifyGridMask(mask_3d, indexToModify, modifyValue);
451          break;
452        case 4:
453          modifyGridMask(mask_4d, indexToModify, modifyValue);
454          break;
455        case 5:
456          modifyGridMask(mask_5d, indexToModify, modifyValue);
457          break;
458        case 6:
459          modifyGridMask(mask_6d, indexToModify, modifyValue);
460          break;
461        case 7:
462          modifyGridMask(mask_7d, indexToModify, modifyValue);
463          break;
464        default:
465          break;
466      }
467   }
468
469   /*
470     Change the mask size. This function is used on reconstructing mask in server side
471     \param [in] newDimensionSize
472     \param [in] newValue
473   */
474   void CGrid::modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue)
475   {     
476      std::vector<CDomain*> domainP = this->getDomains();
477      std::vector<CAxis*> axisP = this->getAxis();           
478      int dim = domainP.size() * 2 + axisP.size();
479
480      switch (dim) {
481        case 0:
482          modifyGridMaskSize(mask_0d, newDimensionSize, newValue);
483          break;
484        case 1:
485          modifyGridMaskSize(mask_1d, newDimensionSize, newValue);
486          break;
487        case 2:
488          modifyGridMaskSize(mask_2d, newDimensionSize, newValue);
489          break;
490        case 3:
491          modifyGridMaskSize(mask_3d, newDimensionSize, newValue);
492          break;
493        case 4:
494          modifyGridMaskSize(mask_4d, newDimensionSize, newValue);
495          break;
496        case 5:
497          modifyGridMaskSize(mask_5d, newDimensionSize, newValue);
498          break;
499        case 6:
500          modifyGridMaskSize(mask_6d, newDimensionSize, newValue);
501          break;
502        case 7:
503          modifyGridMaskSize(mask_7d, newDimensionSize, newValue);
504          break;
505        default:
506          break;
507      }
508   }
509
510   //---------------------------------------------------------------
511
512   void CGrid::solveDomainRef(bool sendAtt)
513   {
514      setDomainList();
515      std::vector<CDomain*> domListP = this->getDomains();
516      if (!domListP.empty())
517      {
518        for (int i = 0; i < domListP.size(); ++i)
519        {
520          if (sendAtt) domListP[i]->sendCheckedAttributes();
521          else domListP[i]->checkAttributesOnClient();
522        }
523      }
524   }
525
526   //---------------------------------------------------------------
527
528   void CGrid::solveAxisRef(bool sendAtt)
529   {
530      setAxisList();
531      std::vector<CAxis*> axisListP = this->getAxis();
532      if (!axisListP.empty())
533      {
534        int idx = 0;
535        axisPositionInGrid_.resize(0);
536        for (int i = 0; i < axis_domain_order.numElements(); ++i)
537        {
538          int elementDimension = axis_domain_order(i);
539          if (1 == elementDimension)
540          {
541            axisPositionInGrid_.push_back(idx);
542            ++idx;
543          }
544          else if (2 == elementDimension) idx += 2;
545        }
546
547        for (int i = 0; i < axisListP.size(); ++i)
548        {
549          if (sendAtt)
550            axisListP[i]->sendCheckedAttributes(getGlobalDimension(),axisPositionInGrid_[i]);
551          else
552            axisListP[i]->checkAttributesOnClient();
553        }
554      }
555   }
556
557   //---------------------------------------------------------------
558
559   void CGrid::solveScalarRef(bool sendAtt)
560   {
561      setScalarList();
562      std::vector<CScalar*> scalarListP = this->getScalars();
563      if (!scalarListP.empty())
564      {
565        for (int i = 0; i < scalarListP.size(); ++i)
566        {
567          /*Nothing to do for now */
568//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
569//          else scalarListP[i]->checkAttributesOnClient();
570        }
571      }
572   }
573
574   /*!
575      Compute the index to for write data into a file
576   */
577   void CGrid::computeWrittenIndex()
578   {     
579      if (computedWrittenIndex_) return;
580      computedWrittenIndex_ = true;
581
582      if (isScalarGrid())
583      {
584        size_t nbWritten = 1;
585        int writtenIndex = 0;
586
587        localIndexToWriteOnClient.resize(nbWritten); 
588        localIndexToWriteOnServer.resize(nbWritten);
589        localIndexToWriteOnServer(0) = writtenIndex;
590        localIndexToWriteOnClient(0) = writtenIndex;
591       
592        return;
593      }
594
595      size_t nbWritten = 0, indGlo;
596      CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
597      CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(),
598                                                              ite = globalDataIndex.end(), it;   
599      const CDistributionServer::GlobalLocalMap& globalLocalIndex = serverDistribution_->getGlobalLocalIndex();                                                             
600      CDistributionServer::GlobalLocalMap::const_iterator itSrvb = globalLocalIndex.begin(),
601                                                          itSrve = globalLocalIndex.end(), itSrv;
602      for (it = itb; it != ite; ++it)
603      {
604        indGlo = it->first;
605        if (globalLocalIndex.end() != globalLocalIndex.find(indGlo)) ++nbWritten;               
606      }
607
608      localIndexToWriteOnClient.resize(nbWritten); 
609      localIndexToWriteOnServer.resize(nbWritten);
610     
611      {
612        numberWrittenIndexes_ = nbWritten;
613        if (isDataDistributed_)
614        {
615          CContextServer* server = CContext::getCurrent()->server;     
616          MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
617          MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
618          offsetWrittenIndexes_ -= numberWrittenIndexes_;
619        }
620        else
621          totalNumberWrittenIndexes_ = numberWrittenIndexes_;
622      }
623
624      nbWritten = 0; 
625      for (it = itb; it != ite; ++it)
626      {
627        indGlo = it->first;
628        itSrv = globalLocalIndex.find(indGlo);
629        if (itSrve != itSrv)
630        {
631          localIndexToWriteOnServer(nbWritten) = itSrv->second;
632          localIndexToWriteOnClient(nbWritten) = it->second;
633          ++nbWritten;               
634        } 
635      }
636   }
637
638   //---------------------------------------------------------------
639
640   /*
641     Compute the global index and its local index taking account mask and data index.
642     These global indexes will be used to compute the connection of this client (sender) to its servers (receivers)
643     (via function computeConnectedClient)
644     These global indexes also correspond to data sent to servers (if any)
645   */
646   void CGrid::computeClientIndex()
647   {
648     CContext* context = CContext::getCurrent();
649
650     CContextClient* client = context->client;  // Here it's not important which contextClient to recuperate
651     int rank = client->clientRank;
652
653     clientDistribution_ = new CDistributionClient(rank, this);
654     // Get local data index on client
655     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
656     int nbStoreIndex = storeIndex_client.numElements();
657     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
658
659     if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed();
660     else
661     {
662        // Mapping global index received from clients to the storeIndex_client
663        CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
664        CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
665        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
666                                               ite = outGlobalIndexFromClient.end(), it;
667
668        for (it = itb; it != ite; ++it)
669        {
670          int rank = it->first;
671          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
672          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
673          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
674          size_t nbIndex = 0;
675
676          // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
677          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
678          {
679            if (itGloe != globalDataIndex.find(globalIndex(idx)))
680            {
681              ++nbIndex;
682            }
683          }
684
685          if (doGridHaveDataDistributed(client) && (nbIndex != localIndex.numElements()))
686               ERROR("void CGrid::computeClientIndex()",
687                  << "Number of local index on client is different from number of received global index"
688                  << "Rank of sent client " << rank <<"."
689                  << "Number of local index " << nbIndex << ". "
690                  << "Number of received global index " << localIndex.numElements() << ".");
691
692          nbIndex = 0;
693          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
694          {
695            if (itGloe != globalDataIndex.find(globalIndex(idx)))
696            {
697              localIndex(idx) = globalDataIndex[globalIndex(idx)];
698            }
699          }
700        }
701      }
702   }
703
704   /*!
705     Compute connected receivers and indexes to be sent to these receivers.
706   */
707   void CGrid::computeConnectedClients()
708   {
709     CContext* context = CContext::getCurrent();
710     int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size();
711     connectedServerRank_.clear();
712     connectedDataSize_.clear();
713     globalIndexOnServer_.clear();
714     nbSenders.clear();
715
716     for (int p = 0; p < nbSrvPools; ++p)
717     {
718       CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p];
719       int receiverSize = client->serverSize;
720//       connectedServerRank_[client].clear();
721
722       if (connectedServerRank_.find(receiverSize) == connectedServerRank_.end())
723       {
724        if (!doGridHaveDataDistributed(client))
725         {
726            if (client->isServerLeader())
727            {
728              size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
729              const std::list<int>& ranks = client->getRanksServerLeader();
730              for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
731              {
732                connectedServerRank_[receiverSize].push_back(*itRank);
733                connectedDataSize_[receiverSize][*itRank] = ssize;
734              }
735            }
736            return;
737         }
738
739         // Compute mapping between client and server
740         std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
741         CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
742         std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
743                                                                                                    client->clientRank,
744                                                                                                    client->clientSize,
745                                                                                                    axis_domain_order,
746                                                                                                    getDistributedDimension());
747
748         // Even if servers have no index, they must received something from client
749         // We only use several client to send "empty" message to these servers
750         std::list<int> serverZeroIndexLeader;
751         std::list<int> serverZeroIndexNotLeader;
752         CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
753         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
754           *it = serverZeroIndex[*it];
755
756         if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end())
757           computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]);
758
759         const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
760         CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
761         CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
762         itbGlobalMap = globalIndexOnServer_[receiverSize].begin();
763         iteGlobalMap = globalIndexOnServer_[receiverSize].end();
764
765         for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
766         {
767           int serverRank = itGlobalMap->first;
768           int indexSize = itGlobalMap->second.size();
769           const std::vector<size_t>& indexVec = itGlobalMap->second;
770           for (int idx = 0; idx < indexSize; ++idx)
771           {
772              itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
773              if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
774              {
775                if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank))
776                  connectedDataSize_[receiverSize][serverRank] = 1;
777                else
778                  ++connectedDataSize_[receiverSize][serverRank];
779              }
780           }
781         }
782
783         // Connected servers which really have index
784         for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
785           connectedServerRank_[receiverSize].push_back(itGlobalMap->first);
786         }
787
788         // Connected servers which have no index at all
789         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
790           connectedServerRank_[receiverSize].push_back(*it);
791
792         // Even if a client has no index, it must connect to at least one server and
793         // send an "empty" data to this server
794         if (connectedServerRank_[receiverSize].empty())
795          connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);
796
797         nbSenders[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);
798       }
799     }
800   }
801
802   /*!
803     Compute the global index of grid to send to server as well as the connected server of the current client.
804     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
805     their global index. We can have a map of global index of grid and local index that each client holds
806     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
807     of the current client.
808   */
809   void CGrid::computeIndex(void)
810   {
811     CContext* context = CContext::getCurrent();
812     if (isScalarGrid())
813     {
814       computeClientIndexScalarGrid();
815       if (context->hasClient)
816       {
817         computeConnectedClientsScalarGrid();
818       }
819     }
820     else
821     {
822       computeClientIndex();
823       if (context->hasClient)
824       {
825         computeConnectedClients();
826       }
827     }
828     if (CServer::serverLevel==2)
829     {
830       computeWrittenIndex() ;
831       if (serverDistribution_!=0) serverDistribution_->partialClear() ;
832       if (clientDistribution_!=0) clientDistribution_->partialClear() ;
833       outGlobalIndexFromClient.clear() ;
834     }
835   }
836
837   /*!
838      Compute the global of (client) grid to send to server with the global index of each element of grid
839      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
840      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
841      on each element whose size is much smaller than one of whole grid.
842      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
843      \param [in] client contextClient
844      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
845   */
846   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
847                                     const CContextClient* client,
848                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
849   {
850     int serverSize = client->serverSize;
851
852     std::vector<CDomain*> domList = getDomains();
853     std::vector<CAxis*> axisList = getAxis();
854
855     // Some pre-calculations of global index on each element of current grid.
856     int nbElement = axis_domain_order.numElements();
857     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
858     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
859     std::vector<size_t> elementNGlobal(nbElement);
860     elementNGlobal[0] = 1;
861     size_t globalSize = 1;
862     for (int idx = 0; idx < nbElement; ++idx)
863     {
864       elementNGlobal[idx] = globalSize;
865       size_t elementSize;
866       size_t elementGlobalSize = 1;
867       if (2 == axis_domain_order(idx)) // This is domain
868       {
869         elementSize = domList[domainIdx]->i_index.numElements();
870         globalIndexElement[idx].resize(elementSize);
871         for (int jdx = 0; jdx < elementSize; ++jdx)
872         {
873           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
874         }
875         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
876         ++domainIdx;
877       }
878       else if (1 == axis_domain_order(idx))  // This is axis
879       {
880         elementSize = axisList[axisIdx]->index.numElements();
881         globalIndexElement[idx].resize(elementSize);
882         for (int jdx = 0; jdx < elementSize; ++jdx)
883         {
884           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
885         }
886         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
887         ++axisIdx;
888       }
889       else  // Of course, this is scalar
890       {
891         globalIndexElement[idx].resize(1);
892         globalIndexElement[idx](0) = 0;
893         elementGlobalSize = 1;
894       }
895       globalSize *= elementGlobalSize;
896     }
897
898     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
899     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
900     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
901     // Number of temporary distributed global index held by each client for each server
902     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
903     CArray<int,1> nbIndexOnServerTmp(serverSize);
904     for (int idx = 0; idx < nbElement; ++idx)
905     {
906       nbIndexOnServer = 0;
907       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
908       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
909       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
910       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
911       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
912       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
913                                                                    ite = globalIndexElementOnServerMap.end(), it;
914       for (it = itb; it != ite; ++it)
915       {
916         const std::vector<int>& tmp = it->second;
917         nbIndexOnServerTmp = 0;
918         for (int i = 0; i < tmp.size(); ++i)
919         {
920           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
921         }
922         nbIndexOnServer += nbIndexOnServerTmp;
923       }
924
925       for (int i = 0; i < serverSize; ++i)
926       {
927         if (0 != nbIndexOnServer(i))
928         {
929           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
930           elementOnServer[idx][i] = true;
931         }
932       }
933
934     nbIndexOnServer = 0;
935     for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
936     {
937       it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
938       if (it != ite)
939       {
940         const std::vector<int>& tmp = it->second;
941         nbIndexOnServerTmp = 0;
942         for (int i = 0; i < tmp.size(); ++i)
943         {
944           if (0 == nbIndexOnServerTmp(tmp[i]))
945           {
946             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
947             ++nbIndexOnServerTmp(tmp[i]);
948           }
949         }
950         nbIndexOnServer += nbIndexOnServerTmp;
951       }
952     }
953   }
954
955    // Determine server which contain global source index
956    std::vector<bool> intersectedProc(serverSize, true);
957    for (int idx = 0; idx < nbElement; ++idx)
958    {
959      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
960                     intersectedProc.begin(), intersectedProc.begin(),
961                     std::logical_and<bool>());
962    }
963
964    std::vector<int> srcRank;
965    for (int idx = 0; idx < serverSize; ++idx)
966    {
967      if (intersectedProc[idx]) srcRank.push_back(idx);
968    }
969
970    // Compute the global index of grid from global index of each element.
971    for (int i = 0; i < srcRank.size(); ++i)
972    {
973      size_t ssize = 1;
974      int rankSrc = srcRank[i];
975      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
976      std::vector<size_t> currentIndex(nbElement,0);
977      for (int idx = 0; idx < nbElement; ++idx)
978      {
979        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
980        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
981      }
982      globalIndexOnServer[rankSrc].resize(ssize);
983
984      std::vector<int> idxLoop(nbElement,0);
985      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
986      size_t idx = 0;
987      while (idx < ssize)
988      {
989        for (int ind = 0; ind < nbElement; ++ind)
990        {
991          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
992          {
993            idxLoop[ind] = 0;
994            ++idxLoop[ind+1];
995          }
996
997          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
998        }
999
1000        for (int ind = 0; ind < innnerLoopSize; ++ind)
1001        {
1002          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
1003          size_t globalSrcIndex = 0;
1004          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
1005          {
1006            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
1007          }
1008          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
1009          ++idx;
1010          ++idxLoop[0];
1011        }
1012      }
1013    }
1014   }
1015   //----------------------------------------------------------------
1016
1017   CGrid* CGrid::createGrid(CDomain* domain)
1018   {
1019      std::vector<CDomain*> vecDom(1, domain);
1020      std::vector<CAxis*> vecAxis;
1021
1022      return createGrid(vecDom, vecAxis);
1023   }
1024
1025   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
1026   {
1027      std::vector<CDomain*> vecDom(1, domain);
1028      std::vector<CAxis*> vecAxis(1, axis);
1029
1030      return createGrid(vecDom, vecAxis);
1031   }
1032
1033   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1034                            const CArray<int,1>& axisDomainOrder)
1035   {
1036     std::vector<CScalar*> vecScalar;
1037     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
1038   }
1039
1040   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1041                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1042   {
1043     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
1044   }
1045
1046   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1047                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1048   {
1049      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1050        ERROR("CGrid* CGrid::createGrid(...)",
1051              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1052              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1053
1054      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
1055      grid->setDomainList(domains);
1056      grid->setAxisList(axis);
1057      grid->setScalarList(scalars);
1058
1059      // By default, domains are always the first elements of a grid
1060      if (0 == axisDomainOrder.numElements())
1061      {
1062        int size = domains.size() + axis.size() + scalars.size();
1063        int nb = 0;
1064        grid->axis_domain_order.resize(size);
1065        for (int i = 0; i < size; ++i)
1066        {
1067          if (i < domains.size()) {
1068            grid->axis_domain_order(i) = 2;
1069
1070          }
1071          else if ((scalars.size() < (size-nb)) < size) {
1072            grid->axis_domain_order(i) = 1;
1073          }
1074          else
1075            grid->axis_domain_order(i) = 0;
1076          ++nb;
1077        }
1078      }
1079      else
1080      {
1081        grid->axis_domain_order.resize(axisDomainOrder.numElements());
1082        grid->axis_domain_order = axisDomainOrder;
1083      }
1084
1085      grid->solveDomainAxisRefInheritance(true);
1086
1087      return grid;
1088   }
1089
1090   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
1091   {
1092     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
1093     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
1094     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
1095
1096     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
1097     {
1098       CDomain* domain = CDomain::createDomain();
1099       domain->duplicateAttributes(domainSrcTmp[idx]);
1100       domain->duplicateTransformation(domainSrcTmp[idx]);
1101       domain->solveRefInheritance(true);
1102       domain->solveInheritanceTransformation();
1103       domainSrc.push_back(domain);
1104     }
1105
1106     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
1107     {
1108       CAxis* axis = CAxis::createAxis();
1109       axis->duplicateAttributes(axisSrcTmp[idx]);
1110       axis->duplicateTransformation(axisSrcTmp[idx]);
1111       axis->solveRefInheritance(true);
1112       axis->solveInheritanceTransformation();
1113       axisSrc.push_back(axis);
1114     }
1115
1116     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
1117     {
1118       CScalar* scalar = CScalar::createScalar();
1119       scalar->duplicateAttributes(scalarSrcTmp[idx]);
1120       scalar->duplicateTransformation(scalarSrcTmp[idx]);
1121       scalar->solveRefInheritance(true);
1122       scalar->solveInheritanceTransformation();
1123       scalarSrc.push_back(scalar);
1124     }
1125
1126      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
1127
1128      return grid;
1129   }
1130
1131   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1132                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1133   {
1134      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1135        ERROR("CGrid* CGrid::generateId(...)",
1136              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1137              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1138
1139      std::ostringstream id;
1140
1141      if (domains.empty() && axis.empty() && !scalars.empty())
1142        id << "__scalar_";
1143
1144      if (0 != (domains.size() + axis.size() + scalars.size()))
1145      {
1146        id << "__grid";
1147
1148        if (0 == axisDomainOrder.numElements())
1149        {
1150          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
1151          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
1152          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
1153        }
1154        else
1155        {
1156          size_t iDomain = 0, iAxis = 0, iScalar = 0;
1157          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
1158          {
1159            if (2 == axisDomainOrder(i))
1160              id << "_" << domains[iDomain++]->getId();
1161            else if (1 == axisDomainOrder(i))
1162              id << "_" << axis[iAxis++]->getId();
1163            else
1164              id << "_" << scalars[iScalar++]->getId();
1165          }
1166        }
1167
1168        id << "__";
1169      }
1170
1171      return id.str();
1172   }
1173
1174   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
1175   {
1176     StdString idSrc  = gridSrc->getId();
1177     StdString idDest = gridDest->getId();
1178
1179     std::ostringstream id;
1180     id << idSrc << "__" << idDest;
1181
1182     return id.str();
1183   }
1184
1185   //----------------------------------------------------------------
1186
1187   CDomainGroup* CGrid::getVirtualDomainGroup() const
1188   {
1189     return this->vDomainGroup_;
1190   }
1191
1192   CAxisGroup* CGrid::getVirtualAxisGroup() const
1193   {
1194     return this->vAxisGroup_;
1195   }
1196
1197   CScalarGroup* CGrid::getVirtualScalarGroup() const
1198   {
1199     return this->vScalarGroup_;
1200   }
1201
1202/*
1203   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
1204   {
1205     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
1206     StdSize numElements = stored.numElements();
1207     for (StdSize n = 0; n < numElements; ++n)
1208     {
1209       field[out_i(n)] = stored(n);
1210     }
1211   }
1212
1213   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
1214   {
1215     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
1216     StdSize numElements = stored.numElements();
1217     for (StdSize n = 0; n < numElements; ++n)
1218     {
1219       stored(n) = field[out_i(n)];
1220     }
1221   }
1222
1223   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
1224   {
1225     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
1226     StdSize numElements = stored.numElements();
1227     for (StdSize n = 0; n < numElements; ++n)
1228     {
1229       field[out_i(n)] = stored(n);
1230     }
1231   }
1232*/
1233   //----------------------------------------------------------------
1234
1235   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
1236   {
1237      const StdSize size = storeIndex_client.numElements();
1238
1239      stored.resize(size);
1240      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1241   }
1242
1243   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
1244   {
1245      const StdSize size = storeIndex_client.numElements();
1246
1247      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
1248   }
1249
1250   void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) const
1251   {
1252      const std::vector<int>& localMaskedDataIndex = clientDistribution_->getLocalMaskedDataIndexOnClient();
1253      const int size = localMaskedDataIndex.size();
1254     
1255      for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i];
1256   }
1257
1258
1259  void CGrid::computeClientIndexScalarGrid()
1260  {
1261    CContext* context = CContext::getCurrent();   
1262//    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; // This should be changed soon
1263//    for (int p = 0; p < nbSrvPools; ++p)
1264    {
1265//      CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client)
1266//                                                    : context->client;
1267      CContextClient* client = context->client;
1268
1269      int rank = client->clientRank;
1270
1271      clientDistribution_ = new CDistributionClient(rank, this);
1272
1273      storeIndex_client.resize(1);
1274      storeIndex_client(0) = 0;     
1275
1276      if (0 != serverDistribution_)
1277      {
1278        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
1279                                               ite = outGlobalIndexFromClient.end(), it;
1280        for (it = itb; it != ite; ++it)
1281        {
1282          int rank = it->first;
1283          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1284          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1285          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
1286          if (1 != globalIndex.numElements())
1287            ERROR("void CGrid::computeClientIndexScalarGrid()",
1288              << "Something wrong happened. "
1289              << "Number of received global index on scalar grid should equal to 1" 
1290              << "Number of received global index " << globalIndex.numElements() << ".");
1291
1292          localIndex(0) = globalIndex(0);
1293        }
1294      }
1295    }
1296  }
1297
1298  void CGrid::computeConnectedClientsScalarGrid()
1299  {
1300    CContext* context = CContext::getCurrent();   
1301    int nbSrvPools = (context->clientPrimServer.size()==0) ? 1 : context->clientPrimServer.size();
1302    connectedServerRank_.clear();
1303    connectedDataSize_.clear();
1304    nbSenders.clear();
1305
1306    for (int p = 0; p < nbSrvPools; ++p)
1307    {
1308      CContextClient* client = (context->clientPrimServer.size()==0) ? context->client : context->clientPrimServer[p];
1309      int receiverSize = client->serverSize;
1310
1311//      connectedServerRank_[client].clear();
1312
1313      if (connectedServerRank_.find(receiverSize)==connectedServerRank_.end())
1314      {
1315        if (client->isServerLeader())
1316        {
1317          const std::list<int>& ranks = client->getRanksServerLeader();
1318          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1319          {
1320            int rank = *itRank;
1321            int nb = 1;
1322            connectedServerRank_[receiverSize].push_back(rank);
1323            connectedDataSize_[receiverSize][rank] = nb;
1324            nbSenders[receiverSize][rank] = nb;
1325          }
1326        }
1327        else
1328        {
1329          const std::list<int>& ranks = client->getRanksServerNotLeader();
1330          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1331          {
1332            int rank = *itRank;
1333            int nb = 1;
1334            connectedServerRank_[receiverSize].push_back(rank);
1335            connectedDataSize_[receiverSize][rank] = nb;
1336            nbSenders[receiverSize][rank] = nb;
1337          }
1338        }
1339      }
1340      isDataDistributed_ = false;
1341    }
1342  }
1343
1344  void CGrid::sendIndexScalarGrid()
1345  {
1346    CContext* context = CContext::getCurrent();
1347    storeIndex_toSrv.clear();
1348    std::list<CContextClient*>::iterator it;
1349
1350    for (it=clients.begin(); it!=clients.end(); ++it)
1351    {
1352      CContextClient* client = *it;
1353      int receiverSize = client->serverSize;
1354
1355      CEventClient event(getType(), EVENT_ID_INDEX);
1356      list<CMessage> listMsg;
1357      list<CArray<size_t,1> > listOutIndex;
1358
1359      if (client->isServerLeader())
1360      {
1361        const std::list<int>& ranks = client->getRanksServerLeader();
1362        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1363        {
1364          int rank = *itRank;
1365          int nb = 1;
1366          storeIndex_toSrv[client].insert(std::make_pair(rank, CArray<int,1>(nb)));
1367          listOutIndex.push_back(CArray<size_t,1>(nb));
1368
1369          CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank];
1370          CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1371
1372          for (int k = 0; k < nb; ++k)
1373          {
1374            outGlobalIndexOnServer(k) = 0;
1375            outLocalIndexToServer(k)  = 0;
1376          }
1377
1378          if (context->hasClient && !context->hasServer)
1379            storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1380
1381          listMsg.push_back(CMessage());
1382          listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
1383
1384          event.push(rank, 1, listMsg.back());
1385        }
1386        client->sendEvent(event);
1387      }
1388      else
1389      {
1390        const std::list<int>& ranks = client->getRanksServerNotLeader();
1391        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1392        {
1393          int rank = *itRank;
1394          int nb = 1;         
1395          CArray<int, 1> outLocalIndexToServer(nb);
1396          for (int k = 0; k < nb; ++k)
1397          {
1398            outLocalIndexToServer(k)  = 0;
1399          }
1400
1401          if (context->hasClient && !context->hasServer)
1402            storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1403        }
1404        client->sendEvent(event);
1405      }
1406    }
1407  }
1408
1409  void CGrid::sendIndex(void)
1410  {
1411    CContext* context = CContext::getCurrent();
1412    storeIndex_toSrv.clear();
1413    std::list<CContextClient*>::iterator it;
1414
1415    for (it=clients.begin(); it!=clients.end(); ++it)
1416    {
1417      CContextClient* client = *it;
1418      int receiverSize = client->serverSize;
1419
1420      CEventClient event(getType(), EVENT_ID_INDEX);
1421      int rank;
1422      list<CMessage> listMsg;
1423      list<CArray<size_t,1> > listOutIndex;
1424      const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
1425      CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex,
1426                                                              iteIndex = globalLocalIndexSendToServer.end();
1427      itIndex = itbIndex;                                                             
1428
1429      if (!doGridHaveDataDistributed(client))
1430      {
1431        if (client->isServerLeader())
1432        {
1433          int indexSize = globalLocalIndexSendToServer.size();
1434          CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1435          CArray<int,1> outLocalIndexToServer(indexSize);
1436          for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1437          {
1438            outGlobalIndexOnServer(idx) = itIndex->first;
1439            outLocalIndexToServer(idx) = itIndex->second;
1440          }
1441
1442          const std::list<int>& ranks = client->getRanksServerLeader();
1443          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1444          {
1445            storeIndex_toSrv[client].insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1446            if (context->hasClient && !context->hasServer)
1447              storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1448           
1449            listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1450
1451            listMsg.push_back(CMessage());
1452            listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1453
1454            event.push(*itRank, 1, listMsg.back());
1455          }
1456          client->sendEvent(event);
1457        }
1458        else
1459        {
1460           int indexSize = globalLocalIndexSendToServer.size();
1461           CArray<int,1> outLocalIndexToServer(indexSize);
1462           for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1463           {
1464             outLocalIndexToServer(idx) = itIndex->second;
1465           }
1466
1467           const std::list<int>& ranks = client->getRanksServerNotLeader();
1468           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1469           {
1470             storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1471           }
1472           client->sendEvent(event);
1473         }
1474      }
1475      else
1476      {
1477        CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
1478        itGlobalMap = globalIndexOnServer_[receiverSize].begin();
1479        iteGlobalMap = globalIndexOnServer_[receiverSize].end();
1480
1481        std::map<int,std::vector<int> >localIndexTmp;
1482        std::map<int,std::vector<size_t> > globalIndexTmp;
1483        for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1484        {
1485          int serverRank = itGlobalMap->first;
1486          int indexSize = itGlobalMap->second.size();
1487          const std::vector<size_t>& indexVec = itGlobalMap->second;
1488          for (int idx = 0; idx < indexSize; ++idx)
1489          {
1490            itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
1491            if (iteIndex != itIndex)
1492            {
1493              globalIndexTmp[serverRank].push_back(itIndex->first);
1494              localIndexTmp[serverRank].push_back(itIndex->second);
1495            }
1496          }
1497        }
1498
1499        for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns)
1500        {
1501          rank = connectedServerRank_[receiverSize][ns];
1502          int nb = 0;
1503          if (globalIndexTmp.end() != globalIndexTmp.find(rank))
1504            nb = globalIndexTmp[rank].size();
1505
1506          storeIndex_toSrv[client].insert(make_pair(rank, CArray<int,1>(nb)));
1507          listOutIndex.push_back(CArray<size_t,1>(nb));
1508
1509          CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank];
1510          CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1511
1512          for (int k = 0; k < nb; ++k)
1513          {
1514            outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1515            outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1516          }
1517
1518          storeIndex_fromSrv.insert(make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1519          listMsg.push_back(CMessage());
1520          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1521
1522          event.push(rank, nbSenders[receiverSize][rank], listMsg.back());
1523        }
1524
1525        client->sendEvent(event);
1526      }
1527    }
1528  }
1529
1530  void CGrid::recvIndex(CEventServer& event)
1531  {
1532    string gridId;
1533    vector<int> ranks;
1534    vector<CBufferIn*> buffers;
1535
1536    list<CEventServer::SSubEvent>::iterator it;
1537    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1538    {
1539      ranks.push_back(it->rank);
1540      CBufferIn* buffer = it->buffer;
1541      *buffer >> gridId;
1542      buffers.push_back(buffer);
1543    }
1544    get(gridId)->recvIndex(ranks, buffers);
1545  }
1546
1547  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1548  {
1549    CContext* context = CContext::getCurrent();
1550    connectedServerRankRead_ = ranks;
1551
1552    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
1553    nbSrvPools = 1;   
1554    nbReadSenders.clear();
1555    for (int p = 0; p < nbSrvPools; ++p)
1556    {
1557      CContextServer* server = (!context->hasClient) ? context->server : context->serverPrimServer[p];
1558      CContextClient* client = context->client;   //(!context->hasClient) ? context->client : context->clientPrimServer[p];
1559     
1560      int idx = 0, numElement = axis_domain_order.numElements();
1561      int ssize = numElement;
1562      std::vector<int> indexMap(numElement);
1563      for (int i = 0; i < numElement; ++i)
1564      {
1565        indexMap[i] = idx;
1566        if (2 == axis_domain_order(i))
1567        {
1568          ++ssize;
1569          idx += 2;
1570        }
1571        else
1572          ++idx;
1573      }
1574
1575      for (int n = 0; n < ranks.size(); n++)
1576      {
1577        int rank = ranks[n];
1578        CBufferIn& buffer = *buffers[n];
1579
1580        buffer >> isDataDistributed_ >> isCompressible_;
1581        size_t dataSize = 0;
1582
1583        if (0 == serverDistribution_)
1584        {
1585          int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1586          std::vector<CDomain*> domainList = getDomains();
1587          std::vector<CAxis*> axisList = getAxis();
1588          std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize), nGlobElement(numElement);
1589          std::vector<CArray<int,1> > globalZoomIndex(numElement);
1590          for (int i = 0; i < numElement; ++i)
1591          {
1592            nGlobElement[i] = globalSize;
1593            if (2 == axis_domain_order(i)) //domain
1594            {
1595              nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin;
1596              nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni;
1597              nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;             
1598              nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1599
1600              nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
1601              nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj;
1602              nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;             
1603              nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1604
1605              {
1606                int count = 0;
1607                globalZoomIndex[i].resize(nZoomSize[indexMap[i]]*nZoomSize[indexMap[i]+1]);
1608                for (int jdx = 0; jdx < nZoomSize[indexMap[i]+1]; ++jdx)
1609                  for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)               
1610                  {
1611                    globalZoomIndex[i](count) = (nZoomBegin[indexMap[i]] + idx) + (nZoomBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
1612                    ++count;
1613                  }
1614              }
1615
1616              ++domainId;
1617            }
1618            else if (1 == axis_domain_order(i)) // axis
1619            {
1620              nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin;
1621              nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_n;
1622              nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;             
1623              nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
1624              if (axisList[axisId]->zoomByIndex())
1625              {
1626                globalZoomIndex[i].reference(axisList[axisId]->zoom_index);               
1627              }
1628              else
1629              {
1630                globalZoomIndex[i].resize(nZoomSize[indexMap[i]]);
1631                for (int idx = 0; idx < nZoomSize[indexMap[i]]; ++idx)
1632                  globalZoomIndex[i](idx) = nZoomBegin[indexMap[i]] + idx;
1633              }
1634
1635              ++axisId;
1636            }
1637            else // scalar
1638            { 
1639              nZoomBegin[indexMap[i]] = 0;
1640              nZoomSize[indexMap[i]]  = 1;
1641              nZoomBeginGlobal[indexMap[i]] = 0;             
1642              nGlob[indexMap[i]] = 1;
1643              globalZoomIndex[i].resize(1);
1644              globalZoomIndex[i](0) = 0;
1645              ++scalarId;
1646            }
1647          }
1648          dataSize = 1;
1649
1650          for (int i = 0; i < nZoomSize.size(); ++i)
1651            dataSize *= nZoomSize[i];
1652          serverDistribution_ = new CDistributionServer(server->intraCommRank, 
1653                                                        globalZoomIndex, axis_domain_order,
1654                                                        nZoomBegin, nZoomSize, nZoomBeginGlobal, nGlob);
1655        }
1656
1657        CArray<size_t,1> outIndex;
1658        buffer >> outIndex;
1659        outGlobalIndexFromClient.insert(std::make_pair(rank, outIndex));
1660        connectedDataSizeRead_[rank] = outIndex.numElements();
1661
1662        if (doGridHaveDataDistributed(client))
1663        {}
1664        else
1665        {
1666          // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
1667          // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
1668          dataSize = serverDistribution_->getGridSize();
1669        }
1670        writtenDataSize_ += dataSize;
1671      }
1672
1673
1674      // Compute mask of the current grid
1675      {
1676        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
1677        std::vector<CDomain*> domainList = getDomains();
1678        std::vector<CAxis*> axisList = getAxis();
1679        int dimSize = 2 * domainList.size() + axisList.size();
1680        std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize);       
1681        for (int i = 0; i < numElement; ++i)
1682        {         
1683          if (2 == axis_domain_order(i)) //domain
1684          {
1685            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
1686            nSize[indexMap[i]]  = domainList[domainId]->ni;
1687            nBeginGlobal[indexMap[i]] = 0;             
1688            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1689
1690            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
1691            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
1692            nBeginGlobal[indexMap[i] + 1] = 0;             
1693            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1694
1695            ++domainId;
1696          }
1697          else if (1 == axis_domain_order(i)) // axis
1698          {
1699            nBegin[indexMap[i]] = axisList[axisId]->begin;
1700            nSize[indexMap[i]]  = axisList[axisId]->n;
1701            nBeginGlobal[indexMap[i]] = 0;             
1702            nGlob[indexMap[i]] = axisList[axisId]->n_glo;             
1703            ++axisId;
1704          }
1705          else // scalar
1706          { 
1707          }
1708        }
1709       
1710        if (nSize.empty()) // Scalar grid
1711        {
1712          nBegin.push_back(0);
1713          nSize.push_back(1);
1714          nBeginGlobal.push_back(0);             
1715          nGlob.push_back(1); 
1716        }
1717
1718        modifyMaskSize(nSize, false);
1719
1720        // These below codes are reserved for future
1721        CDistributionServer srvDist(server->intraCommRank, nBegin, nSize, nBeginGlobal, nGlob); 
1722        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
1723                                               ite = outGlobalIndexFromClient.end(), it; 
1724        const CDistributionServer::GlobalLocalMap&  globalLocalMask = srvDist.getGlobalLocalIndex();
1725        CDistributionServer::GlobalLocalMap::const_iterator itSrv;
1726        size_t nb = 0;
1727        for (it = itb; it != ite; ++it)
1728        {
1729          CArray<size_t,1>& globalInd = it->second;
1730          for (size_t idx = 0; idx < globalInd.numElements(); ++idx)
1731          {
1732            if (globalLocalMask.end() != globalLocalMask.find(globalInd(idx))) ++nb;
1733          }
1734        }
1735       
1736        CArray<int,1> indexToModify(nb);
1737        nb = 0;   
1738        for (it = itb; it != ite; ++it)
1739        {
1740          CArray<size_t,1>& globalInd = it->second;
1741          for (size_t idx = 0; idx < globalInd.numElements(); ++idx)
1742          {
1743            itSrv = globalLocalMask.find(globalInd(idx));
1744            if (globalLocalMask.end() != itSrv) 
1745            {
1746              indexToModify(nb) = itSrv->second;
1747              ++nb;
1748            }
1749          }
1750        }
1751
1752        modifyMask(indexToModify, true);
1753      }
1754
1755      if (isScalarGrid()) return;
1756
1757      nbReadSenders[client] = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1758    }
1759  }
1760
1761  /*
1762     Compute on the fly the global dimension of a grid with its elements
1763     \param[in/out] globalDim global dimension of grid
1764     \param[in] domains list of its domains
1765     \param[in] axiss list of its axis
1766     \param[in] scalars list of its scalars
1767     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1768     \return The dimension of which we do distribution (often for server)
1769  */
1770  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1771                                        const std::vector<CDomain*> domains,
1772                                        const std::vector<CAxis*> axis,
1773                                        const std::vector<CScalar*> scalars,
1774                                        const CArray<int,1>& axisDomainOrder)
1775  {
1776 //   globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1777    globalDim.resize(domains.size()*2+axis.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    if (clientsSet.find(contextClient)==clientsSet.end())
2509    {
2510      clients.push_back(contextClient) ;
2511      clientsSet.insert(contextClient);
2512    }
2513    for (int i=0; i<this->getDomains().size(); i++)
2514        this->getDomains()[i]->setContextClient(contextClient);
2515    for (int i=0; i<this->getAxis().size(); i++)
2516        this->getAxis()[i]->setContextClient(contextClient);
2517  }
2518
2519  /*!
2520    Parse a grid, for now, it contains only domain, axis and scalar
2521  */
2522  void CGrid::parse(xml::CXMLNode& node)
2523  {
2524    SuperClass::parse(node);
2525
2526    if (node.goToChildElement())
2527    {
2528      StdString domainName("domain");
2529      StdString axisName("axis");
2530      StdString scalarName("scalar");
2531      do
2532      {
2533        if (node.getElementName() == domainName) {
2534          order_.push_back(2);
2535          this->getVirtualDomainGroup()->parseChild(node);
2536        }
2537        if (node.getElementName() == axisName) {
2538          order_.push_back(1);
2539          this->getVirtualAxisGroup()->parseChild(node);
2540        }
2541        if (node.getElementName() == scalarName) {
2542          order_.push_back(0);
2543          this->getVirtualScalarGroup()->parseChild(node);
2544        }
2545      } while (node.goToNextElement());
2546      node.goToParentElement();
2547    }
2548
2549    if (!order_.empty())
2550    {
2551      int sizeOrd = order_.size();
2552      axis_domain_order.resize(sizeOrd);
2553      for (int i = 0; i < sizeOrd; ++i)
2554      {
2555        axis_domain_order(i) = order_[i];
2556      }
2557    }
2558
2559    setDomainList();
2560    setAxisList();
2561    setScalarList();
2562   }
2563} // namespace xios
Note: See TracBrowser for help on using the repository browser.