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

Last change on this file since 1202 was 1202, checked in by mhnguyen, 7 years ago

Porting non-continuous axis zoom to dev branch

+) Port axis zoom
+) Resolve some merge conflicts
+) Revert some codes

Test
+) On Curie
+) Ok

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