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

Last change on this file since 1346 was 1345, checked in by oabramkina, 6 years ago

In addition to r1294: all domain/axis attributes are only sent to secondary-server pools that need them (and not to all pools).

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