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

Last change on this file since 1234 was 1232, checked in by mhnguyen, 7 years ago

Fixing the blocking problem where there are more servers than the number of grid band distribution

+) Correct this problem not only for writing but also for reading
+) Allow "zero-size" domain, axis (i.e: domain, axis with ni = 0, and/or nj=0)

Test
+) On Curie
+) Work in both cases: Read and Write data

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