source: XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp @ 1227

Last change on this file since 1227 was 1215, checked in by ymipsl, 7 years ago

Distribute files on servers 2 -> Ok test_dcmip2

YM

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