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

Last change on this file since 1594 was 1594, checked in by oabramkina, 5 years ago

Bugfix on dev: NaNs? were not necessarily replaced upon writing by default_value in case of grid mask.

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