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

Last change on this file since 1054 was 1054, checked in by oabramkina, 6 years ago

dev: intermediate commit.

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