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

Last change on this file since 1099 was 1099, checked in by mhnguyen, 5 years ago

Updating 2-level server

+) Make some changes in the way data rebuilt on each level of server
+) Make some changes in the order of functions call during close context to make sure that each server receives the global indexes before calculating index to send to next level
+) Modify some functions to make sure data sent to the correct server pool

Test
+) On Curie
+) Only test_client

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