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

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

Exception handling on trunk.

To activate it, compilation flag -DXIOS_EXCEPTION should be added.

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