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

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

Two server levels: merging trunk r1200 (except for non-contiguous zoom) into dev. Tested on Curie. Todo: non-contiguous zoom.

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