source: XIOS/trunk/src/node/grid.cpp @ 871

Last change on this file since 871 was 865, checked in by mhnguyen, 8 years ago

Optimizing codes: Change the way to compute distribution of grid

+) Instead of using DHT on grid, we make use of it only for elements of grid
+) Make change to calculation of server distribution.

Test
+) On Curie
+) Two times faster than the precedent commit.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 55.7 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20
21namespace xios {
22
23   /// ////////////////////// Dfinitions ////////////////////// ///
24
25   CGrid::CGrid(void)
26      : CObjectTemplate<CGrid>(), CGridAttributes()
27      , isChecked(false), isDomainAxisChecked(false)
28      , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false)
29      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
30      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
31      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
32      , transformations_(0), isTransformed_(false)
33      , axisPositionInGrid_(), positionDimensionDistributed_(1), hasDomainAxisBaseRef_(false)
34      , gridSrc_(), hasTransform_(false), order_(), globalIndexOnServer_()
35   {
36     setVirtualDomainGroup();
37     setVirtualAxisGroup();
38   }
39
40   CGrid::CGrid(const StdString& id)
41      : CObjectTemplate<CGrid>(id), CGridAttributes()
42      , isChecked(false), isDomainAxisChecked(false)
43      , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false)
44      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
45      , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
46      , globalDim_(), connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)
47      , transformations_(0), isTransformed_(false)
48      , axisPositionInGrid_(), positionDimensionDistributed_(1), hasDomainAxisBaseRef_(false)
49      , gridSrc_(), hasTransform_(false), order_(), globalIndexOnServer_()
50   {
51     setVirtualDomainGroup();
52     setVirtualAxisGroup();
53   }
54
55   CGrid::~CGrid(void)
56   {
57    if (0 != clientDistribution_) delete clientDistribution_;
58    if (0 != serverDistribution_) delete serverDistribution_;
59    if (0 != clientServerMap_) delete clientServerMap_;
60    if (0 != transformations_) delete transformations_;
61   }
62
63   ///---------------------------------------------------------------
64
65   StdString CGrid::GetName(void)    { return StdString("grid"); }
66   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
67   ENodeType CGrid::GetType(void)    { return eGrid; }
68
69
70   StdSize CGrid::getDimension(void) const
71   {
72      return globalDim_.size();
73   }
74
75   //---------------------------------------------------------------
76
77   StdSize CGrid::getDataSize(void) const
78   {
79     StdSize retvalue = 1;
80     if (!isScalarGrid())
81     {
82       std::vector<int> dataNindex = clientDistribution_->getDataNIndex();
83       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];
84     }
85     return retvalue;
86   }
87
88   /*!
89    * Compute the minimum buffer size required to send the attributes to the server(s).
90    *
91    * \return A map associating the server rank with its minimum buffer size.
92    */
93   std::map<int, StdSize> CGrid::getAttributesBufferSize()
94   {
95     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
96
97     // The grid indexes require a similar size as the actual data
98     std::map<int, StdSize> dataSizes = getDataBufferSize();
99     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
100     for (it = dataSizes.begin(); it != itE; ++it)
101     {
102       it->second += 2 * sizeof(bool);
103       if (it->second > attributesSizes[it->first])
104         attributesSizes[it->first] = it->second;
105     }
106
107     // Account for the axis attributes
108     std::vector<CAxis*> axisList = getAxis();
109     for (size_t i = 0; i < axisList.size(); ++i)
110     {
111       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize();
112       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
113       {
114         if (it->second > attributesSizes[it->first])
115           attributesSizes[it->first] = it->second;
116       }
117     }
118
119     // Account for the domain attributes
120     std::vector<CDomain*> domList = getDomains();
121     for (size_t i = 0; i < domList.size(); ++i)
122     {
123       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize();
124       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
125       {
126         if (it->second > attributesSizes[it->first])
127           attributesSizes[it->first] = it->second;
128       }
129     }
130
131     return attributesSizes;
132   }
133
134   /*!
135    * Compute the minimum buffer size required to send the data to the server(s).
136    *
137    * \param id the id used to tag the data
138    * \return A map associating the server rank with its minimum buffer size.
139    */
140   std::map<int, StdSize> CGrid::getDataBufferSize(const std::string& id /*= ""*/)
141   {
142     std::map<int, StdSize> dataSizes;
143     // The record index is sometimes sent along with the data but we always
144     // include it in the size calculation for the sake of simplicity
145     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() + 2 * sizeof(size_t);
146
147     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_.end();
148     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
149     {
150       int rank = connectedServerRank_[k];
151       std::map<int, size_t>::const_iterator it = connectedDataSize_.find(rank);
152       size_t count = (it != itEnd) ? it->second : 0;
153
154       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
155     }
156
157     return dataSizes;
158   }
159
160   void CGrid::checkAttributesAfterTransformation()
161   {
162     setDomainList();
163     std::vector<CDomain*> domListP = this->getDomains();
164     if (!domListP.empty())
165     {
166       for (int i = 0; i < domListP.size(); ++i)
167       {
168         domListP[i]->checkAttributesOnClientAfterTransformation();
169       }
170     }
171   }
172
173   //---------------------------------------------------------------
174
175   /*!
176    * Test whether the data defined on the grid can be outputted in a compressed way.
177    *
178    * \return true if and only if a mask was defined for this grid
179    */
180   bool CGrid::isCompressible(void) const
181   {
182      return isCompressible_;
183   }
184
185   //---------------------------------------------------------------
186
187   void CGrid::addRelFileCompressed(const StdString& filename)
188   {
189      this->relFilesCompressed.insert(filename);
190   }
191
192   bool CGrid::isWrittenCompressed(const StdString& filename) const
193   {
194      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
195   }
196
197   //---------------------------------------------------------------
198
199   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
200   {
201     if (this->isDomainAxisChecked) return;
202
203     this->solveAxisRef(areAttributesChecked);
204     this->solveDomainRef(areAttributesChecked);
205     computeGridGlobalDimension(getDomains(), getAxis(), axis_domain_order);
206     this->isDomainAxisChecked = areAttributesChecked;
207   }
208
209   void CGrid::solveDomainAxisBaseRef()
210   {
211     if (this->hasDomainAxisBaseRef_) return;
212     // Account for the axis attributes
213     std::vector<CAxis*> axisList = getAxis();
214     for (size_t i = 0; i < axisList.size(); ++i)
215     {
216       axisList[i]->setAttributesReference();
217     }
218
219     // Account for the domain attributes
220     std::vector<CDomain*> domList = getDomains();
221     for (size_t i = 0; i < domList.size(); ++i)
222     {
223       domList[i]->setAttributesReference();
224     }
225     this->hasDomainAxisBaseRef_ = true;
226   }
227
228   void CGrid::checkEligibilityForCompressedOutput()
229   {
230     // We don't check if the mask is valid here, just if a mask has been defined at this point.
231     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
232   }
233
234   void CGrid::checkMaskIndex(bool doSendingIndex)
235   {
236     CContext* context = CContext::getCurrent();
237     CContextClient* client=context->client;
238
239     if (isScalarGrid())
240     {
241       if (context->hasClient)
242          if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndexScalarGrid(); this->isIndexSent = true; }
243
244       if (this->isChecked) return;
245       if (context->hasClient)
246       {
247          this->computeIndexScalarGrid();
248       }
249
250       this->isChecked = true;
251       return;
252     }
253
254     if (context->hasClient)
255      if (this->isChecked && doSendingIndex && !isIndexSent) { sendIndex(); this->isIndexSent = true; }
256
257     if (this->isChecked) return;
258
259     if (context->hasClient)
260     {
261        this->checkAttributesAfterTransformation();
262        this->checkMask();
263        this->computeIndex();
264     }
265     this->isChecked = true;
266   }
267
268   void CGrid::createMask(void)
269   {
270      using namespace std;
271      std::vector<CDomain*> domainP = this->getDomains();
272      std::vector<CAxis*> axisP = this->getAxis();
273      int dim = domainP.size() * 2 + axisP.size();
274
275      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
276      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
277      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
278      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
279
280      switch (dim) {
281        case 1:
282          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
283          break;
284        case 2:
285          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
286          break;
287        case 3:
288          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
289          break;
290        default:
291          break;
292      }
293   }
294
295   void CGrid::checkMask(void)
296   {
297      using namespace std;
298      std::vector<CDomain*> domainP = this->getDomains();
299      std::vector<CAxis*> axisP = this->getAxis();
300      int dim = domainP.size() * 2 + axisP.size();
301
302      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
303      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->mask_1d);
304      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
305      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
306
307      switch (dim) {
308        case 1:
309          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
310          break;
311        case 2:
312          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
313          break;
314        case 3:
315          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
316          break;
317//        case 4:
318//          checkGridMask(mask4, domainMasks, axisMasks, axis_domain_order);
319//          break;
320//        case 5:
321//          checkGridMask(mask5, domainMasks, axisMasks, axis_domain_order);
322//          break;
323//        case 6:
324//          checkGridMask(mask6, domainMasks, axisMasks, axis_domain_order);
325//          break;
326//        case 7:
327//          checkGridMask(mask7, domainMasks, axisMasks, axis_domain_order);
328//          break;
329        default:
330          break;
331      }
332   }
333
334   void CGrid::modifyMask(const CArray<int,1>& indexToModify)
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      switch (dim) {
342        case 1:
343          modifyGridMask(mask_1d, indexToModify);
344          break;
345        case 2:
346          modifyGridMask(mask_2d, indexToModify);
347          break;
348        case 3:
349          modifyGridMask(mask_3d, indexToModify);
350          break;
351
352        default:
353          break;
354      }
355   }
356
357   //---------------------------------------------------------------
358
359   void CGrid::solveDomainRef(bool sendAtt)
360   {
361      setDomainList();
362      std::vector<CDomain*> domListP = this->getDomains();
363      if (!domListP.empty())
364      {
365        for (int i = 0; i < domListP.size(); ++i)
366        {
367          if (sendAtt) domListP[i]->sendCheckedAttributes();
368          else domListP[i]->checkAttributesOnClient();
369        }
370      }
371   }
372
373   //---------------------------------------------------------------
374
375   void CGrid::solveAxisRef(bool sendAtt)
376   {
377      setAxisList();
378      std::vector<CAxis*> axisListP = this->getAxis();
379      if (!axisListP.empty())
380      {
381        int idx = 0;
382        axisPositionInGrid_.resize(0);
383        for (int i = 0; i < axis_domain_order.numElements(); ++i)
384        {
385          if (false == axis_domain_order(i))
386          {
387            axisPositionInGrid_.push_back(idx);
388            ++idx;
389          }
390          else idx += 2;
391        }
392
393        for (int i = 0; i < axisListP.size(); ++i)
394        {
395          if (sendAtt)
396            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionInGrid_[i]);
397          else
398            axisListP[i]->checkAttributesOnClient();
399          ++idx;
400        }
401      }
402   }
403
404   std::vector<int> CGrid::getAxisPositionInGrid() const
405   {
406     return axisPositionInGrid_;
407   }
408
409   //---------------------------------------------------------------
410
411   /*!
412     Compute the global index of grid to send to server as well as the connected server of the current client.
413     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
414     their global index. We can have a map of global index of grid and local index that each client holds
415     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
416     of the current client.
417   */
418   void CGrid::computeIndex(void)
419   {
420     CContext* context = CContext::getCurrent();
421     CContextClient* client = context->client;
422
423     // First of all, compute distribution on client side
424     clientDistribution_ = new CDistributionClient(client->clientRank, this);
425     // Get local data index on client
426     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
427     int nbStoreIndex = storeIndex_client.numElements();
428     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
429     isDataDistributed_= clientDistribution_->isDataDistributed();
430
431     if (!doGridHaveDataDistributed())
432     {
433        if (0 == client->clientRank)
434        {
435          size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
436          for (int rank = 0; rank < client->serverSize; ++rank)
437            connectedDataSize_[rank] = ssize;
438        }
439        return;
440     }
441
442     // Compute mapping between client and server
443     std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
444     CServerDistributionDescription serverDistributionDescription(globalDim_, client->serverSize);
445     serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
446                                                                client->clientRank,
447                                                                client->clientSize,
448                                                                axis_domain_order,
449                                                                positionDimensionDistributed_);
450     computeIndexByElement(indexServerOnElement, globalIndexOnServer_);
451
452     const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
453     CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
454     CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
455     itGlobalMap  = itbGlobalMap = globalIndexOnServer_.begin();
456     iteGlobalMap = globalIndexOnServer_.end();
457
458     for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
459     {
460       int serverRank = itGlobalMap->first;
461       int indexSize = itGlobalMap->second.size();
462       const std::vector<size_t>& indexVec = itGlobalMap->second;
463       for (int idx = 0; idx < indexSize; ++idx)
464       {
465          itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
466          if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
467          {
468             if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
469               connectedDataSize_[serverRank] = 1;
470             else
471               ++connectedDataSize_[serverRank];
472          }
473       }
474     }
475
476     connectedServerRank_.clear();
477     for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
478       connectedServerRank_.push_back(itGlobalMap->first);
479     }
480
481     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
482   }
483
484   /*!
485      Compute the global of (client) grid to send to server with the global index of each element of grid
486      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
487      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
488      on each element whose size is much smaller than one of whole grid.
489      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
490      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
491   */
492   void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
493                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
494   {
495     CContext* context = CContext::getCurrent();
496     CContextClient* client = context->client;
497     int serverSize = client->serverSize;
498     std::vector<CDomain*> domList = getDomains();
499     std::vector<CAxis*> axisList = getAxis();
500
501     // Some pre-calculations of global index on each element of current grid.
502     int nbElement = axis_domain_order.numElements();
503     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
504     int domainIdx = 0, axisIdx = 0;
505     std::vector<size_t> elementNGlobal(nbElement);
506     elementNGlobal[0] = 1;
507     size_t globalSize = 1;
508     for (int idx = 0; idx < nbElement; ++idx)
509     {
510       elementNGlobal[idx] = globalSize;
511       size_t elementSize;
512       size_t elementGlobalSize = 1;
513       if (axis_domain_order(idx))
514       {
515         elementSize = domList[domainIdx]->i_index.numElements();
516         globalIndexElement[idx].resize(elementSize);
517         for (int jdx = 0; jdx < elementSize; ++jdx)
518         {
519           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
520         }
521         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
522         ++domainIdx;
523       }
524       else
525       {
526         elementSize = axisList[axisIdx]->index.numElements();
527         globalIndexElement[idx].resize(elementSize);
528         for (int jdx = 0; jdx < elementSize; ++jdx)
529         {
530           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
531         }
532         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
533         ++axisIdx;
534       }
535       globalSize *= elementGlobalSize;
536     }
537
538     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
539     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
540     for (int idx = 0; idx < nbElement; ++idx)
541     {
542       std::vector<int> nbIndexOnServer(serverSize,0);
543       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
544       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
545       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
546       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
547       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
548       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
549                                                                    ite = globalIndexElementOnServerMap.end(), it;
550       for (it = itb; it != ite; ++it)
551       {
552         const std::vector<int>& tmp = it->second;
553         for (int i = 0; i < tmp.size(); ++i)
554         {
555           ++nbIndexOnServer[tmp[i]];
556         }
557       }
558
559       for (int i = 0; i < serverSize; ++i)
560       {
561         if (0 != nbIndexOnServer[i])
562         {
563           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer[i]);
564           nbIndexOnServer[i] = 0;
565           elementOnServer[idx][i] = true;
566         }
567       }
568
569       for (it = itb; it != ite; ++it)
570       {
571         const std::vector<int>& tmp = it->second;
572         for (int i = 0; i < tmp.size(); ++i)
573         {
574           globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer[tmp[i]]] = it->first;
575           ++nbIndexOnServer[tmp[i]];
576         }
577       }
578     }
579
580    // Determine server which contain global source index
581    std::vector<bool> intersectedProc(serverSize, true);
582    for (int idx = 0; idx < nbElement; ++idx)
583    {
584      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
585                     intersectedProc.begin(), intersectedProc.begin(),
586                     std::logical_and<bool>());
587    }
588
589    std::vector<int> srcRank;
590    for (int idx = 0; idx < serverSize; ++idx)
591    {
592      if (intersectedProc[idx]) srcRank.push_back(idx);
593    }
594
595    // Compute the global index of grid from global index of each element.
596    for (int i = 0; i < srcRank.size(); ++i)
597    {
598      size_t ssize = 1;
599      int rankSrc = srcRank[i];
600      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
601      std::vector<size_t> currentIndex(nbElement,0);
602      for (int idx = 0; idx < nbElement; ++idx)
603      {
604        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
605        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
606      }
607      globalIndexOnServer[rankSrc].resize(ssize);
608
609      std::vector<int> idxLoop(nbElement,0);
610      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
611      size_t idx = 0;
612      while (idx < ssize)
613      {
614        for (int ind = 0; ind < nbElement; ++ind)
615        {
616          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
617          {
618            idxLoop[ind] = 0;
619            ++idxLoop[ind+1];
620          }
621
622          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
623        }
624
625        for (int ind = 0; ind < innnerLoopSize; ++ind)
626        {
627          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
628          size_t globalSrcIndex = 0;
629          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
630          {
631            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
632          }
633          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
634          ++idx;
635          ++idxLoop[0];
636        }
637      }
638    }
639   }
640   //----------------------------------------------------------------
641
642   CGrid* CGrid::createGrid(CDomain* domain)
643   {
644      std::vector<CDomain*> vecDom(1, domain);
645      std::vector<CAxis*> vecAxis;
646
647      return createGrid(vecDom, vecAxis);
648   }
649
650   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
651   {
652      std::vector<CDomain*> vecDom(1, domain);
653      std::vector<CAxis*> vecAxis(1, axis);
654
655      return createGrid(vecDom, vecAxis);
656   }
657
658   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
659                            const CArray<bool,1>& axisDomainOrder)
660   {
661      return createGrid(generateId(domains, axis, axisDomainOrder), domains, axis, axisDomainOrder);
662   }
663
664   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
665                            const CArray<bool,1>& axisDomainOrder)
666   {
667      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size()))
668        ERROR("CGrid* CGrid::createGrid(...)",
669              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
670              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
671
672      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
673      grid->setDomainList(domains);
674      grid->setAxisList(axis);
675
676      // By default, domains are always the first elements of a grid
677      if (0 == axisDomainOrder.numElements())
678      {
679        int size = domains.size() + axis.size();
680        grid->axis_domain_order.resize(size);
681        for (int i = 0; i < size; ++i)
682        {
683          if (i < domains.size()) grid->axis_domain_order(i) = true;
684          else grid->axis_domain_order(i) = false;
685        }
686      }
687      else
688      {
689        grid->axis_domain_order.resize(axisDomainOrder.numElements());
690        grid->axis_domain_order = axisDomainOrder;
691      }
692
693      grid->solveDomainAxisRefInheritance(true);
694
695      return grid;
696   }
697
698   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
699   {
700     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
701     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
702     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
703     {
704       CAxis* axis = CAxis::createAxis();
705       axis->duplicateAttributes(axisSrcTmp[idx]);
706       axis->duplicateTransformation(axisSrcTmp[idx]);
707       axis->solveRefInheritance(true);
708       axis->solveInheritanceTransformation();
709       axisSrc.push_back(axis);
710     }
711
712     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
713     {
714       CDomain* domain = CDomain::createDomain();
715       domain->duplicateAttributes(domainSrcTmp[idx]);
716       domain->duplicateTransformation(domainSrcTmp[idx]);
717       domain->solveRefInheritance(true);
718       domain->solveInheritanceTransformation();
719       domainSrc.push_back(domain);
720     }
721
722      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, gridSrc->axis_domain_order);
723
724      return grid;
725   }
726
727   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
728                               const CArray<bool,1>& axisDomainOrder)
729   {
730      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size()))
731        ERROR("CGrid* CGrid::generateId(...)",
732              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
733              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
734
735      std::ostringstream id;
736
737      if (domains.empty() && axis.empty())
738        id << "__scalar_grid__";
739      else
740      {
741        id << "__grid";
742
743        if (0 == axisDomainOrder.numElements())
744        {
745          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
746          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
747        }
748        else
749        {
750          size_t iDomain = 0, iAxis = 0;
751          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
752          {
753            if (axisDomainOrder(i))
754              id << "_" << domains[iDomain++]->getId();
755            else
756              id << "_" << axis[iAxis++]->getId();
757          }
758        }
759
760        id << "__";
761      }
762
763      return id.str();
764   }
765
766   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
767   {
768     StdString idSrc  = gridSrc->getId();
769     StdString idDest = gridDest->getId();
770
771     std::ostringstream id;
772     id << idSrc << "__" << idDest;
773
774     return id.str();
775   }
776
777   //----------------------------------------------------------------
778
779   CDomainGroup* CGrid::getVirtualDomainGroup() const
780   {
781     return this->vDomainGroup_;
782   }
783
784   CAxisGroup* CGrid::getVirtualAxisGroup() const
785   {
786     return this->vAxisGroup_;
787   }
788
789   void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field)
790   {
791     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
792     StdSize numElements = stored.numElements();
793     for (StdSize n = 0; n < numElements; ++n)
794     {
795       field[out_i(n)] = stored(n);
796     }
797   }
798
799   void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored)
800   {
801     const CArray<size_t,1>& out_i = outIndexFromClient[rank];
802     StdSize numElements = stored.numElements();
803     for (StdSize n = 0; n < numElements; ++n)
804     {
805       stored(n) = field[out_i(n)];
806     }
807   }
808
809   void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field)
810   {
811     const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank];
812     StdSize numElements = stored.numElements();
813     for (StdSize n = 0; n < numElements; ++n)
814     {
815       field[out_i(n)] = stored(n);
816     }
817   }
818
819   //----------------------------------------------------------------
820
821   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const
822   {
823      const StdSize size = storeIndex_client.numElements();
824
825      stored.resize(size);
826      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
827   }
828
829   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const
830   {
831      const StdSize size = storeIndex_client.numElements();
832
833      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
834   }
835
836  void CGrid::computeIndexScalarGrid()
837  {
838    CContext* context = CContext::getCurrent();
839    CContextClient* client=context->client;
840
841    storeIndex_client.resize(1);
842    storeIndex_client(0) = 0;
843    if (0 == client->clientRank)
844    {
845      for (int rank = 0; rank < client->serverSize; ++rank)
846        connectedDataSize_[rank] = 1;
847    }
848    isDataDistributed_ = false;
849  }
850
851  void CGrid::computeCompressedIndex()
852  {
853    compressedOutIndexFromClient = outIndexFromClient;
854
855    std::map<size_t, size_t> indexes;
856
857    {
858      std::map<int, CArray<size_t,1> >::const_iterator it = compressedOutIndexFromClient.begin();
859      std::map<int, CArray<size_t,1> >::const_iterator itEnd = compressedOutIndexFromClient.end();
860      for (; it != itEnd; ++it)
861      {
862        for (int i = 0; i < it->second.numElements(); ++i)
863          indexes.insert(std::make_pair(it->second(i), 0));
864      }
865    }
866
867    {
868      std::map<size_t, size_t>::iterator it = indexes.begin();
869      std::map<size_t, size_t>::iterator itEnd = indexes.end();
870      for (size_t i = 0; it != itEnd; ++it, ++i)
871        it->second = i;
872    }
873
874    {
875      std::map<int, CArray<size_t,1> >::iterator it = compressedOutIndexFromClient.begin();
876      std::map<int, CArray<size_t,1> >::iterator itEnd = compressedOutIndexFromClient.end();
877      for (; it != itEnd; ++it)
878      {
879        for (int i = 0; i < it->second.numElements(); ++i)
880          it->second(i) = indexes[it->second(i)];
881      }
882    }
883  }
884
885  void CGrid::sendIndexScalarGrid()
886  {
887    CContext* context = CContext::getCurrent();
888    CContextClient* client = context->client;
889
890    CEventClient event(getType(), EVENT_ID_INDEX);
891    list<CMessage> listMsg;
892    list<CArray<size_t,1> > listOutIndex;
893
894    if (0 == client->clientRank)
895    {
896      for (int rank = 0; rank < client->serverSize; ++rank)
897      {
898        int nb = 1;
899        storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(nb)));
900        listOutIndex.push_back(CArray<size_t,1>(nb));
901
902        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
903        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
904
905        for (int k = 0; k < nb; ++k)
906        {
907          outGlobalIndexOnServer(k) = 0;
908          outLocalIndexToServer(k)  = 0;
909        }
910
911        listMsg.push_back(CMessage());
912        listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back();
913
914        event.push(rank, 1, listMsg.back());
915      }
916
917      client->sendEvent(event);
918    }
919    else
920      client->sendEvent(event);
921  }
922
923  void CGrid::sendIndex(void)
924  {
925    CContext* context = CContext::getCurrent();
926    CContextClient* client = context->client;
927
928    CEventClient event(getType(), EVENT_ID_INDEX);
929    int rank;
930    list<CMessage> listMsg;
931    list<CArray<size_t,1> > listOutIndex;
932//    const CClientServerMapping::GlobalIndexMap& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
933//    const CClientServerMapping::GlobalIndexMap& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
934    const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
935    CDistributionClient::GlobalLocalDataMap::const_iterator itIndex = globalLocalIndexSendToServer.begin(),
936                                                           iteIndex = globalLocalIndexSendToServer.end();
937
938    if (!doGridHaveDataDistributed())
939    {
940      if (0 == client->clientRank)
941      {
942        int indexSize = globalLocalIndexSendToServer.size();
943        CArray<size_t,1> outGlobalIndexOnServer(indexSize);
944        CArray<int,1> outLocalIndexToServer(indexSize);
945        for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
946        {
947          outGlobalIndexOnServer(idx) = itIndex->first;
948          outLocalIndexToServer(idx) = itIndex->second;
949        }
950
951        for (rank = 0; rank < client->serverSize; ++rank)
952        {
953          storeIndex_toSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
954          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
955
956          listMsg.push_back(CMessage());
957          listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
958
959          event.push(rank, 1, listMsg.back());
960        }
961
962        client->sendEvent(event);
963      }
964      else
965        client->sendEvent(event);
966    }
967    else
968    {
969      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
970      itGlobalMap = globalIndexOnServer_.begin();
971      iteGlobalMap = globalIndexOnServer_.end();
972
973      std::map<int,std::vector<int> >localIndexTmp;
974      std::map<int,std::vector<size_t> > globalIndexTmp;
975      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
976      {
977        int serverRank = itGlobalMap->first;
978        int indexSize = itGlobalMap->second.size();
979        const std::vector<size_t>& indexVec = itGlobalMap->second;
980        for (int idx = 0; idx < indexSize; ++idx)
981        {
982          itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
983          if (iteIndex != itIndex)
984          {
985            globalIndexTmp[serverRank].push_back(itIndex->first);
986            localIndexTmp[serverRank].push_back(itIndex->second);
987          }
988        }
989      }
990
991      for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
992      {
993        rank = connectedServerRank_[ns];
994        int nb = 0;
995        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
996          nb = globalIndexTmp[rank].size();
997
998        storeIndex_toSrv.insert(make_pair(rank, CArray<int,1>(nb)));
999        listOutIndex.push_back(CArray<size_t,1>(nb));
1000
1001        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[rank];
1002        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1003
1004        for (int k = 0; k < nb; ++k)
1005        {
1006          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
1007          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
1008        }
1009
1010        listMsg.push_back(CMessage());
1011        listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
1012
1013        event.push(rank, nbSenders[rank], listMsg.back());
1014      }
1015
1016      client->sendEvent(event);
1017    }
1018  }
1019
1020  void CGrid::recvIndex(CEventServer& event)
1021  {
1022    string gridId;
1023    vector<int> ranks;
1024    vector<CBufferIn*> buffers;
1025
1026    list<CEventServer::SSubEvent>::iterator it;
1027    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1028    {
1029      ranks.push_back(it->rank);
1030      CBufferIn* buffer = it->buffer;
1031      *buffer >> gridId;
1032      buffers.push_back(buffer);
1033    }
1034    get(gridId)->recvIndex(ranks, buffers);
1035  }
1036
1037  void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains,
1038                                         const std::vector<CAxis*>& axis,
1039                                         const CArray<bool,1>& axisDomainOrder)
1040  {
1041    globalDim_.resize(domains.size()*2+axis.size());
1042    int idx = 0, idxDomain = 0, idxAxis = 0;
1043    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1044    {
1045      if (axisDomainOrder(i))
1046      {
1047        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1048        {
1049          positionDimensionDistributed_ = idx;
1050        }
1051        else
1052        {
1053          positionDimensionDistributed_ = idx +1;
1054        }
1055
1056        globalDim_[idx]   = domains[idxDomain]->ni_glo.getValue();
1057        globalDim_[idx+1] = domains[idxDomain]->nj_glo.getValue();
1058
1059        ++idxDomain;
1060        idx += 2;
1061      }
1062      else
1063      {
1064        globalDim_[idx] = axis[idxAxis]->n_glo.getValue();
1065        ++idxAxis;
1066        ++idx;
1067      }
1068    }
1069  }
1070
1071  std::vector<int> CGrid::getGlobalDimension()
1072  {
1073    return globalDim_;
1074  }
1075
1076  bool CGrid::isScalarGrid() const
1077  {
1078    return (axisList_.empty() && domList_.empty());
1079  }
1080
1081  /*!
1082    Verify whether one server need to write data
1083    There are some cases on which one server has nodata to write. For example, when we
1084    just only want to zoom on a domain.
1085  */
1086  bool CGrid::doGridHaveDataToWrite()
1087  {
1088     return (0 != writtenDataSize_);
1089  }
1090
1091  /*!
1092    Return size of data which is written on each server
1093    Whatever dimension of a grid, data which are written on server must be presented as
1094    an one dimension array.
1095    \return size of data written on server
1096  */
1097  size_t CGrid::getWrittenDataSize() const
1098  {
1099    return writtenDataSize_;
1100  }
1101
1102  /*!
1103    Returns the number of indexes written by each server.
1104    \return the number of indexes written by each server
1105  */
1106  int CGrid::getNumberWrittenIndexes() const
1107  {
1108    return numberWrittenIndexes_;
1109  }
1110
1111  /*!
1112    Returns the total number of indexes written by the servers.
1113    \return the total number of indexes written by the servers
1114  */
1115  int CGrid::getTotalNumberWrittenIndexes() const
1116  {
1117    return totalNumberWrittenIndexes_;
1118  }
1119
1120  /*!
1121    Returns the offset of indexes written by each server.
1122    \return the offset of indexes written by each server
1123  */
1124  int CGrid::getOffsetWrittenIndexes() const
1125  {
1126    return offsetWrittenIndexes_;
1127  }
1128
1129  CDistributionServer* CGrid::getDistributionServer()
1130  {
1131    return serverDistribution_;
1132  }
1133
1134  CDistributionClient* CGrid::getDistributionClient()
1135  {
1136    return clientDistribution_;
1137  }
1138
1139  bool CGrid::doGridHaveDataDistributed()
1140  {
1141    if (isScalarGrid()) return false;
1142    else
1143      return isDataDistributed_;
1144  }
1145
1146  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers)
1147  {
1148    CContext* context = CContext::getCurrent();
1149    CContextServer* server = context->server;
1150    numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
1151    connectedServerRank_ = ranks;
1152
1153    for (int n = 0; n < ranks.size(); n++)
1154    {
1155      int rank = ranks[n];
1156      CBufferIn& buffer = *buffers[n];
1157
1158      buffer >> isDataDistributed_ >> isCompressible_;
1159      size_t dataSize = 0;
1160
1161      if (isScalarGrid())
1162      {
1163        writtenDataSize_ = numberWrittenIndexes_ = totalNumberWrittenIndexes_ = 1;
1164        CArray<size_t,1> outIndex;
1165        buffer >> outIndex;
1166        outIndexFromClient.insert(std::make_pair(rank, outIndex));
1167        std::vector<int> nZoomBegin(1,0), nZoomSize(1,1), nGlob(1,1), nZoomBeginGlobal(1,0);
1168        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1169                                                      nZoomBeginGlobal, nGlob);
1170        return;
1171      }
1172
1173      if (0 == serverDistribution_)
1174      {
1175        int idx = 0, numElement = axis_domain_order.numElements();
1176        int ssize = numElement;
1177        std::vector<int> indexMap(numElement);
1178        for (int i = 0; i < numElement; ++i)
1179        {
1180          indexMap[i] = idx;
1181          if (true == axis_domain_order(i))
1182          {
1183            ++ssize;
1184            idx += 2;
1185          }
1186          else
1187            ++idx;
1188        }
1189
1190        int axisId = 0, domainId = 0;
1191        std::vector<CDomain*> domainList = getDomains();
1192        std::vector<CAxis*> axisList = getAxis();
1193        std::vector<int> nZoomBegin(ssize), nZoomSize(ssize), nGlob(ssize), nZoomBeginGlobal(ssize);
1194        for (int i = 0; i < numElement; ++i)
1195        {
1196          if (axis_domain_order(i))
1197          {
1198            nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
1199            nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
1200            nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
1201            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
1202
1203            nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
1204            nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
1205            nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
1206            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
1207            ++domainId;
1208          }
1209          else
1210          {
1211            nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
1212            nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
1213            nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
1214            nGlob[indexMap[i]] = axisList[axisId]->n_glo;
1215            ++axisId;
1216          }
1217        }
1218        dataSize = 1;
1219        for (int i = 0; i < nZoomSize.size(); ++i)
1220          dataSize *= nZoomSize[i];
1221
1222        serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
1223                                                      nZoomBeginGlobal, nGlob);
1224      }
1225
1226      CArray<size_t,1> outIndex;
1227      buffer >> outIndex;
1228      if (isDataDistributed_)
1229        serverDistribution_->computeLocalIndex(outIndex);
1230      else
1231      {
1232        dataSize = outIndex.numElements();
1233        for (int i = 0; i < outIndex.numElements(); ++i) outIndex(i) = i;
1234      }
1235      writtenDataSize_ += dataSize;
1236
1237      outIndexFromClient.insert(std::make_pair(rank, outIndex));
1238      connectedDataSize_[rank] = outIndex.numElements();
1239      numberWrittenIndexes_ += outIndex.numElements();
1240    }
1241
1242    if (isDataDistributed_)
1243    {
1244      MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1245      MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1246      offsetWrittenIndexes_ -= numberWrittenIndexes_;
1247    }
1248    else
1249      totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1250
1251    nbSenders = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks);
1252  }
1253
1254   /*!
1255   \brief Dispatch event received from client
1256      Whenever a message is received in buffer of server, it will be processed depending on
1257   its event type. A new event type should be added in the switch list to make sure
1258   it processed on server side.
1259   \param [in] event: Received message
1260   */
1261  bool CGrid::dispatchEvent(CEventServer& event)
1262  {
1263
1264    if (SuperClass::dispatchEvent(event)) return true;
1265    else
1266    {
1267      switch(event.type)
1268      {
1269        case EVENT_ID_INDEX :
1270          recvIndex(event);
1271          return true;
1272          break;
1273
1274         case EVENT_ID_ADD_DOMAIN :
1275           recvAddDomain(event);
1276           return true;
1277           break;
1278
1279         case EVENT_ID_ADD_AXIS :
1280           recvAddAxis(event);
1281           return true;
1282           break;
1283        default :
1284          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1285                << "Unknown Event");
1286          return false;
1287      }
1288    }
1289  }
1290
1291   ///---------------------------------------------------------------
1292
1293   CDomain* CGrid::addDomain(const std::string& id)
1294   {
1295     order_.push_back(true);
1296     axis_domain_order.resize(order_.size());
1297     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1298     return vDomainGroup_->createChild(id);
1299   }
1300
1301   CAxis* CGrid::addAxis(const std::string& id)
1302   {
1303     order_.push_back(false);
1304     axis_domain_order.resize(order_.size());
1305     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
1306     return vAxisGroup_->createChild(id);
1307   }
1308
1309   //! Change virtual field group to a new one
1310   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
1311   {
1312      this->vDomainGroup_ = newVDomainGroup;
1313   }
1314
1315   //! Change virtual variable group to new one
1316   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
1317   {
1318      this->vAxisGroup_ = newVAxisGroup;
1319   }
1320
1321   //----------------------------------------------------------------
1322   //! Create virtual field group, which is done normally on initializing file
1323   void CGrid::setVirtualDomainGroup(void)
1324   {
1325      this->setVirtualDomainGroup(CDomainGroup::create());
1326   }
1327
1328   //! Create virtual variable group, which is done normally on initializing file
1329   void CGrid::setVirtualAxisGroup(void)
1330   {
1331      this->setVirtualAxisGroup(CAxisGroup::create());
1332   }
1333
1334   /*!
1335   \brief Send a message to create a domain on server side
1336   \param[in] id String identity of domain that will be created on server
1337   */
1338   void CGrid::sendAddDomain(const string& id)
1339   {
1340    CContext* context=CContext::getCurrent();
1341
1342    if (! context->hasServer )
1343    {
1344       CContextClient* client=context->client;
1345
1346       CEventClient event(this->getType(),EVENT_ID_ADD_DOMAIN);
1347       if (client->isServerLeader())
1348       {
1349         CMessage msg;
1350         msg<<this->getId();
1351         msg<<id;
1352         const std::list<int>& ranks = client->getRanksServerLeader();
1353         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1354           event.push(*itRank,1,msg);
1355         client->sendEvent(event);
1356       }
1357       else client->sendEvent(event);
1358    }
1359   }
1360
1361   /*!
1362   \brief Send a message to create an axis on server side
1363   \param[in] id String identity of axis that will be created on server
1364   */
1365   void CGrid::sendAddAxis(const string& id)
1366   {
1367    CContext* context=CContext::getCurrent();
1368
1369    if (! context->hasServer )
1370    {
1371       CContextClient* client=context->client;
1372
1373       CEventClient event(this->getType(),EVENT_ID_ADD_AXIS);
1374       if (client->isServerLeader())
1375       {
1376         CMessage msg;
1377         msg<<this->getId();
1378         msg<<id;
1379         const std::list<int>& ranks = client->getRanksServerLeader();
1380         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1381           event.push(*itRank,1,msg);
1382         client->sendEvent(event);
1383       }
1384       else client->sendEvent(event);
1385    }
1386   }
1387
1388   /*!
1389   \brief Receive a message annoucing the creation of a domain on server side
1390   \param[in] event Received event
1391   */
1392   void CGrid::recvAddDomain(CEventServer& event)
1393   {
1394
1395      CBufferIn* buffer = event.subEvents.begin()->buffer;
1396      string id;
1397      *buffer >> id;
1398      get(id)->recvAddDomain(*buffer);
1399   }
1400
1401   /*!
1402   \brief Receive a message annoucing the creation of a domain on server side
1403   \param[in] buffer Buffer containing message
1404   */
1405   void CGrid::recvAddDomain(CBufferIn& buffer)
1406   {
1407      string id;
1408      buffer >> id;
1409      addDomain(id);
1410   }
1411
1412   /*!
1413   \brief Receive a message annoucing the creation of an axis on server side
1414   \param[in] event Received event
1415   */
1416   void CGrid::recvAddAxis(CEventServer& event)
1417   {
1418
1419      CBufferIn* buffer = event.subEvents.begin()->buffer;
1420      string id;
1421      *buffer >> id;
1422      get(id)->recvAddAxis(*buffer);
1423   }
1424
1425   /*!
1426   \brief Receive a message annoucing the creation of an axis on server side
1427   \param[in] buffer Buffer containing message
1428   */
1429   void CGrid::recvAddAxis(CBufferIn& buffer)
1430   {
1431      string id;
1432      buffer >> id;
1433      addAxis(id);
1434   }
1435
1436  /*!
1437  \brief Solve domain and axis references
1438  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1439  all attributes from their parents, they should be processed with this function
1440  \param[in] apply inherit all attributes of parents (true)
1441  */
1442  void CGrid::solveDomainAxisRefInheritance(bool apply)
1443  {
1444    CContext* context = CContext::getCurrent();
1445    unsigned int vecSize, i;
1446    std::vector<StdString>::iterator it, itE;
1447    setDomainList();
1448    it = domList_.begin(); itE = domList_.end();
1449    for (; it != itE; ++it)
1450    {
1451      CDomain* pDom = CDomain::get(*it);
1452      if (context->hasClient)
1453      {
1454        pDom->solveRefInheritance(apply);
1455        pDom->solveInheritanceTransformation();
1456      }
1457    }
1458
1459    setAxisList();
1460    it = axisList_.begin(); itE = axisList_.end();
1461    for (; it != itE; ++it)
1462    {
1463      CAxis* pAxis = CAxis::get(*it);
1464      if (context->hasClient)
1465      {
1466        pAxis->solveRefInheritance(apply);
1467        pAxis->solveInheritanceTransformation();
1468      }
1469    }
1470  }
1471
1472  bool CGrid::isTransformed()
1473  {
1474    return isTransformed_;
1475  }
1476
1477  void CGrid::setTransformed()
1478  {
1479    isTransformed_ = true;
1480  }
1481
1482  CGridTransformation* CGrid::getTransformations()
1483  {
1484    return transformations_;
1485  }
1486
1487  void CGrid::addTransGridSource(CGrid* gridSrc)
1488  {
1489    if (gridSrc_.end() == gridSrc_.find(gridSrc))
1490      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
1491  }
1492
1493  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
1494  {
1495    return gridSrc_;
1496  }
1497
1498  /*!
1499     Complete all the necessary (and lacking) attributes of a grid
1500     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
1501  */
1502  void CGrid::completeGrid(CGrid* transformGridSrc)
1503  {
1504    if (0 != transformGridSrc)
1505    {
1506      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1507      {
1508        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1509             << "Two grids have different dimension size"
1510             << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1511             << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1512      }
1513      else
1514      {
1515        int ssize = axis_domain_order.numElements();
1516        for (int i = 0; i < ssize; ++i)
1517          if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1518            ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
1519                  << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1520                  << " don't have elements in the same order");
1521      }
1522    }
1523
1524    CGridGenerate gridGenerate(this, transformGridSrc);
1525    gridGenerate.completeGrid();
1526  }
1527
1528  void CGrid::transformGrid(CGrid* transformGridSrc)
1529  {
1530    if (!transformGridSrc)
1531      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1532            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
1533
1534    if (isTransformed()) return;
1535    setTransformed();
1536    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
1537    {
1538      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1539           << "Two grids have different dimension size"
1540           << "Dimension of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
1541           << "Dimension of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
1542    }
1543    else
1544    {
1545      int ssize = axis_domain_order.numElements();
1546      for (int i = 0; i < ssize; ++i)
1547        if (axis_domain_order(i) != (transformGridSrc->axis_domain_order)(i))
1548          ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
1549                << "Grids " << this->getId() << " and " << transformGridSrc->getId()
1550                << " don't have elements in the same order");
1551    }
1552
1553    transformations_ = new CGridTransformation(this, transformGridSrc);
1554    transformations_->computeAll();
1555    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
1556
1557    // Ok, now need to compute index of grid source
1558    transformGridSrc->checkMaskIndex(false);
1559  }
1560
1561  bool CGrid::hasTransform()
1562  {
1563    return hasTransform_;
1564  }
1565
1566  /*!
1567  \brief Get the list of domain pointers
1568  \return list of domain pointers
1569  */
1570  std::vector<CDomain*> CGrid::getDomains()
1571  {
1572    std::vector<CDomain*> domList;
1573    if (!domList_.empty())
1574    {
1575      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
1576    }
1577    return domList;
1578  }
1579
1580  /*!
1581  \brief Get the list of  axis pointers
1582  \return list of axis pointers
1583  */
1584  std::vector<CAxis*> CGrid::getAxis()
1585  {
1586    std::vector<CAxis*> aList;
1587    if (!axisList_.empty())
1588      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
1589
1590    return aList;
1591  }
1592
1593  /*!
1594  \brief Set domain(s) of a grid from a list
1595  \param[in] domains list of domains
1596  */
1597  void CGrid::setDomainList(const std::vector<CDomain*> domains)
1598  {
1599    if (isDomListSet) return;
1600    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1601    if (!domains.empty() && domList.empty())
1602    {
1603      for (int i = 0; i < domains.size(); ++i)
1604        this->getVirtualDomainGroup()->addChild(domains[i]);
1605      domList = this->getVirtualDomainGroup()->getAllChildren();
1606    }
1607
1608    if (!domList.empty())
1609    {
1610      int sizeDom = domList.size();
1611      domList_.resize(sizeDom);
1612      for (int i = 0; i < sizeDom; ++i)
1613      {
1614        domList_[i] = domList[i]->getId();
1615      }
1616      isDomListSet = true;
1617    }
1618
1619  }
1620
1621  /*!
1622  \brief Set axis(s) of a grid from a list
1623  \param[in] axis list of axis
1624  */
1625  void CGrid::setAxisList(const std::vector<CAxis*> axis)
1626  {
1627    if (isAxisListSet) return;
1628    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1629    if (!axis.empty() && aList.empty())
1630    {
1631      for (int i = 0; i < axis.size(); ++i)
1632        this->getVirtualAxisGroup()->addChild(axis[i]);
1633      aList = this->getVirtualAxisGroup()->getAllChildren();
1634    }
1635
1636    if (!aList.empty())
1637    {
1638      int sizeAxis = aList.size();
1639      axisList_.resize(sizeAxis);
1640      for (int i = 0; i < sizeAxis; ++i)
1641      {
1642        axisList_[i] = aList[i]->getId();
1643      }
1644      isAxisListSet = true;
1645    }
1646  }
1647
1648  /*!
1649  \brief Get list of id of domains
1650  \return id list of domains
1651  */
1652  std::vector<StdString> CGrid::getDomainList()
1653  {
1654    setDomainList();
1655    return domList_;
1656  }
1657
1658  /*!
1659  \brief Get list of id of axis
1660  \return id list of axis
1661  */
1662  std::vector<StdString> CGrid::getAxisList()
1663  {
1664    setAxisList();
1665    return axisList_;
1666  }
1667
1668  void CGrid::sendAllDomains()
1669  {
1670    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
1671    int dSize = domList.size();
1672    for (int i = 0; i < dSize; ++i)
1673    {
1674      sendAddDomain(domList[i]->getId());
1675      domList[i]->sendAllAttributesToServer();
1676    }
1677  }
1678
1679  void CGrid::sendAllAxis()
1680  {
1681    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
1682    int aSize = aList.size();
1683
1684    for (int i = 0; i < aSize; ++i)
1685    {
1686      sendAddAxis(aList[i]->getId());
1687      aList[i]->sendAllAttributesToServer();
1688    }
1689  }
1690
1691  void CGrid::parse(xml::CXMLNode& node)
1692  {
1693    SuperClass::parse(node);
1694
1695    if (node.goToChildElement())
1696    {
1697      StdString domainName("domain");
1698      StdString axisName("axis");
1699      do
1700      {
1701        if (node.getElementName() == domainName) {
1702          order_.push_back(true);
1703          this->getVirtualDomainGroup()->parseChild(node);
1704        }
1705        if (node.getElementName() == axisName) {
1706          order_.push_back(false);
1707          this->getVirtualAxisGroup()->parseChild(node);
1708        }
1709      } while (node.goToNextElement());
1710      node.goToParentElement();
1711    }
1712
1713    if (!order_.empty())
1714    {
1715      int sizeOrd = order_.size();
1716      axis_domain_order.resize(sizeOrd);
1717      for (int i = 0; i < sizeOrd; ++i)
1718      {
1719        axis_domain_order(i) = order_[i];
1720      }
1721    }
1722
1723    setDomainList();
1724    setAxisList();
1725   }
1726} // namespace xios
Note: See TracBrowser for help on using the repository browser.