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

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

Two server levels: adding files missing in r1158.

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