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

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

Replacing axis zoom by axis extract.
Zoom private attributes are gone for good.

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