source: XIOS/dev/branch_openmp/src/node/grid.cpp @ 1642

Last change on this file since 1642 was 1642, checked in by yushan, 5 years ago

dev on ADA. add flag switch _usingEP/_usingMPI

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