source: XIOS/branchs/xios-2.5/src/node/grid.cpp @ 1627

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

Bugfix for NEMO-like land processes elimination.

Values describing a domain (latitude, longitude, bounds,...) are set to -1 on land processes.

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