source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp @ 1943

Last change on this file since 1943 was 1943, checked in by ymipsl, 4 years ago

Solve issues for grid mask on server side.

YM

  • 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: 116.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#include "server.hpp"
21#include "distribution_type.hpp"
22#include "grid_remote_connector.hpp"
23#include "grid_elements.hpp"
24#include "grid_local_view.hpp"
25#include "grid_mask_connector.hpp"
26
27
28namespace xios {
29
30   /// ////////////////////// Dfinitions ////////////////////// ///
31
32   CGrid::CGrid(void)
33      : CObjectTemplate<CGrid>(), CGridAttributes()
34      , isChecked(false), isDomainAxisChecked(false)
35      , vDomainGroup_(), domList_(), isDomListSet(false)
36      , vAxisGroup_(), axisList_(), isAxisListSet(false)
37      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
38      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
39      , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
40      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
41            , isCompressible_(false)
42      , transformations_(0), isTransformed_(false)
43      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
44      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
45      , computedWrittenIndex_(false)
46      , clients()
47   {
48     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
49     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
50     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
51   }
52
53   CGrid::CGrid(const StdString& id)
54      : CObjectTemplate<CGrid>(id), CGridAttributes()
55      , isChecked(false), isDomainAxisChecked(false)
56      , vDomainGroup_(), domList_(), isDomListSet(false)
57      , vAxisGroup_(), axisList_(), isAxisListSet(false)
58      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
59      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
60      , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
61      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
62            , isCompressible_(false)
63      , transformations_(0), isTransformed_(false)
64      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
65      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
66      , computedWrittenIndex_(false)
67      , clients()
68   {
69     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
70     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
71     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
72   }
73
74   CGrid::~CGrid(void)
75   {
76    if (0 != clientDistribution_) delete clientDistribution_;
77    if (0 != serverDistribution_) delete serverDistribution_;
78    if (0 != clientServerMap_) delete clientServerMap_;
79    if (0 != transformations_) delete transformations_;
80   }
81
82   ///---------------------------------------------------------------
83
84   StdString CGrid::GetName(void)    { return StdString("grid"); }
85   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
86   ENodeType CGrid::GetType(void)    { return eGrid; }
87
88
89  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91  /////////              MEMBER FUNCTION RELATED TO GRID CONSTRUCTION by ELEMNTS AND MANAGEMENT                      /////
92  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
94
95
96   CGrid* CGrid::createGrid(CDomain* domain)
97   TRY
98   {
99     std::vector<CDomain*> vecDom(1, domain);
100     std::vector<CAxis*> vecAxis;
101     return createGrid(vecDom, vecAxis);
102   }
103   CATCH
104
105   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
106   TRY
107  {
108      std::vector<CDomain*> vecDom(1, domain);
109      std::vector<CAxis*> vecAxis(1, axis);
110
111      return createGrid(vecDom, vecAxis);
112   }
113   CATCH
114
115   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
116                            const CArray<int,1>& axisDomainOrder)
117   TRY
118   {
119     std::vector<CScalar*> vecScalar;
120     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
121   }
122   CATCH
123
124   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
125                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
126   TRY
127   {
128     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
129   }
130   CATCH
131
132   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
133                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
134   TRY
135   {
136      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
137        ERROR("CGrid* CGrid::createGrid(...)",
138              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
139              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
140
141      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
142      grid->setDomainList(domains);
143      grid->setAxisList(axis);
144      grid->setScalarList(scalars);
145
146      // By default, domains are always the first elements of a grid
147      if (0 == axisDomainOrder.numElements())
148      {
149        int size = domains.size() + axis.size() + scalars.size();
150        int nb = 0;
151        grid->axis_domain_order.resize(size);
152        for (int i = 0; i < size; ++i)
153        {
154          if (i < domains.size())
155          {
156            grid->axis_domain_order(i) = 2;
157            grid->order_.push_back(2) ;
158          }
159          else if ((scalars.size() < (size-nb)) < size)
160          {
161            grid->axis_domain_order(i) = 1;
162            grid->order_.push_back(1) ;
163          }
164          else
165          {
166            grid->axis_domain_order(i) = 0;
167            grid->order_.push_back(0) ;
168          }
169          ++nb;
170        }
171      }
172      else
173      {
174        grid->axis_domain_order.resize(axisDomainOrder.numElements());
175        grid->axis_domain_order = axisDomainOrder;
176        grid->order_.clear() ;
177        for(int i=0; i<axisDomainOrder.numElements();i++) grid->order_.push_back(axisDomainOrder(i)) ;
178
179      }
180
181 //     grid->solveElementsRefInheritance(true);
182
183      return grid;
184   }
185   CATCH
186
187   //----------------------------------------------------------------
188
189   //! Change virtual field group to a new one
190   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
191   TRY
192   {
193      this->vDomainGroup_ = newVDomainGroup;
194   }
195   CATCH_DUMP_ATTR
196
197   //! Change virtual variable group to new one
198   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
199   TRY
200   {
201      this->vAxisGroup_ = newVAxisGroup;
202   }
203   CATCH_DUMP_ATTR
204
205   //! Change virtual variable group to new one
206   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
207   TRY
208   {
209      this->vScalarGroup_ = newVScalarGroup;
210   }
211   CATCH_DUMP_ATTR
212
213   //----------------------------------------------------------------
214
215   CDomainGroup* CGrid::getVirtualDomainGroup() const
216   TRY
217   {
218     return this->vDomainGroup_;
219   }
220   CATCH
221
222   CAxisGroup* CGrid::getVirtualAxisGroup() const
223   TRY
224   {
225     return this->vAxisGroup_;
226   }
227   CATCH
228
229   CScalarGroup* CGrid::getVirtualScalarGroup() const
230   TRY
231   {
232     return this->vScalarGroup_;
233   }
234   CATCH
235
236  ///---------------------------------------------------------------
237
238   CDomain* CGrid::addDomain(const std::string& id)
239   TRY
240   {
241     order_.push_back(2);
242     axis_domain_order.resize(order_.size());
243     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
244     return vDomainGroup_->createChild(id);
245   }
246   CATCH_DUMP_ATTR
247
248   CAxis* CGrid::addAxis(const std::string& id)
249   TRY
250   {
251     order_.push_back(1);
252     axis_domain_order.resize(order_.size());
253     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
254     return vAxisGroup_->createChild(id);
255   }
256   CATCH_DUMP_ATTR
257
258   CScalar* CGrid::addScalar(const std::string& id)
259   TRY
260   {
261     order_.push_back(0);
262     axis_domain_order.resize(order_.size());
263     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
264     return vScalarGroup_->createChild(id);
265   }
266   CATCH_DUMP_ATTR
267
268
269
270
271  /*!
272  \brief Get the list of domain pointers
273  \return list of domain pointers
274  */
275  std::vector<CDomain*> CGrid::getDomains()
276  TRY
277  {
278    setDomainList();
279    std::vector<CDomain*> domList;
280    if (!domList_.empty())
281    {
282      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
283    }
284    return domList;
285  }
286  CATCH_DUMP_ATTR
287
288  /*!
289  \brief Get the list of  axis pointers
290  \return list of axis pointers
291  */
292  std::vector<CAxis*> CGrid::getAxis()
293  TRY
294  {
295    setAxisList();
296    std::vector<CAxis*> aList;
297    if (!axisList_.empty())
298      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
299
300    return aList;
301  }
302  CATCH_DUMP_ATTR
303
304  /*!
305  \brief Get the list of  axis pointers
306  \return list of axis pointers
307  */
308  std::vector<CScalar*> CGrid::getScalars()
309  TRY
310  {
311    setScalarList() ;
312    std::vector<CScalar*> sList;
313    if (!scalarList_.empty())
314      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
315
316    return sList;
317  }
318  CATCH_DUMP_ATTR
319
320  /*!
321  \brief Get domain pointer with index
322  \return domain pointer
323  */
324  CDomain* CGrid::getDomain(int domainIndex)
325  TRY
326  {
327    std::vector<CDomain*> domainListP = this->getDomains();
328    if (domainListP.empty())
329    {
330      ERROR("CGrid::getDomain(int domainIndex)",
331            << "No domain associated to this grid. " << std::endl
332            << "Grid id = " << this->getId());
333    }
334
335    if (domainIndex >= domainListP.size() || (domainIndex < 0))
336      ERROR("CGrid::getDomain(int domainIndex)",
337            << "Domain with the index doesn't exist " << std::endl
338            << "Grid id = " << this->getId() << std::endl
339            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
340
341    return domainListP[domainIndex];
342  }
343  CATCH_DUMP_ATTR
344
345  /*!
346  \brief Get the axis pointer with index
347  \return axis pointer
348  */
349  CAxis* CGrid::getAxis(int axisIndex)
350  TRY
351  {
352    std::vector<CAxis*> axisListP = this->getAxis();
353    if (axisListP.empty())
354    {
355      ERROR("CGrid::getDomain(int axisIndex)",
356            << "No axis associated to this grid. " << std::endl
357            << "Grid id = " << this->getId());
358    }
359
360    if (axisIndex >= axisListP.size() || (axisIndex < 0))
361      ERROR("CGrid::getDomain(int axisIndex)",
362            << "Domain with the index doesn't exist " << std::endl
363            << "Grid id = " << this->getId() << std::endl
364            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
365
366    return axisListP[axisIndex];
367  }
368  CATCH_DUMP_ATTR
369
370  /*!
371  \brief Get the a scalar pointer
372  \return scalar pointer
373  */
374  CScalar* CGrid::getScalar(int scalarIndex)
375  TRY
376  {
377    std::vector<CScalar*> scalarListP = this->getScalars();
378    if (scalarListP.empty())
379    {
380      ERROR("CGrid::getScalar(int scalarIndex)",
381            << "No scalar associated to this grid. " << std::endl
382            << "Grid id = " << this->getId());
383    }
384
385    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
386      ERROR("CGrid::getScalar(int scalarIndex)",
387            << "Scalar with the index doesn't exist " << std::endl
388            << "Grid id = " << this->getId() << std::endl
389            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
390
391    return scalarListP[scalarIndex];
392  }
393  CATCH_DUMP_ATTR
394
395  /*!
396  \brief Set domain(s) of a grid from a list
397  \param[in] domains list of domains
398  */
399  void CGrid::setDomainList(const std::vector<CDomain*> domains)
400  TRY
401  {
402    if (isDomListSet) return;
403    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
404    if (!domains.empty() && domList.empty())
405    {
406      for (int i = 0; i < domains.size(); ++i)
407        this->getVirtualDomainGroup()->addChild(domains[i]);
408      domList = this->getVirtualDomainGroup()->getAllChildren();
409    }
410
411    if (!domList.empty())
412    {
413      int sizeDom = domList.size();
414      domList_.resize(sizeDom);
415      for (int i = 0; i < sizeDom; ++i)
416      {
417        domList_[i] = domList[i]->getId();
418      }
419      isDomListSet = true;
420    }
421  }
422  CATCH_DUMP_ATTR
423
424  /*!
425  \brief Set axis(s) of a grid from a list
426  \param[in] axis list of axis
427  */
428  void CGrid::setAxisList(const std::vector<CAxis*> axis)
429  TRY
430  {
431    if (isAxisListSet) return;
432    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
433    if (!axis.empty() && aList.empty())
434    {
435      for (int i = 0; i < axis.size(); ++i)
436        this->getVirtualAxisGroup()->addChild(axis[i]);
437      aList = this->getVirtualAxisGroup()->getAllChildren();
438    }
439
440    if (!aList.empty())
441    {
442      int sizeAxis = aList.size();
443      axisList_.resize(sizeAxis);
444      for (int i = 0; i < sizeAxis; ++i)
445      {
446        axisList_[i] = aList[i]->getId();
447      }
448      isAxisListSet = true;
449    }
450  }
451  CATCH_DUMP_ATTR
452
453  /*!
454  \brief Set scalar(s) of a grid from a list
455  \param[in] scalars list of scalars
456  */
457  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
458  TRY
459  {
460    if (isScalarListSet) return;
461    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
462    if (!scalars.empty() && sList.empty())
463    {
464      for (int i = 0; i < scalars.size(); ++i)
465        this->getVirtualScalarGroup()->addChild(scalars[i]);
466      sList = this->getVirtualScalarGroup()->getAllChildren();
467    }
468
469    if (!sList.empty())
470    {
471      int sizeScalar = sList.size();
472      scalarList_.resize(sizeScalar);
473      for (int i = 0; i < sizeScalar; ++i)
474      {
475        scalarList_[i] = sList[i]->getId();
476      }
477      isScalarListSet = true;
478    }
479  }
480  CATCH_DUMP_ATTR
481
482  /*!
483  \brief Get list of id of domains
484  \return id list of domains
485  */
486  std::vector<StdString> CGrid::getDomainList()
487  TRY
488  {
489    setDomainList();
490    return domList_;
491  }
492  CATCH
493
494  /*!
495  \brief Get list of id of axis
496  \return id list of axis
497  */
498  std::vector<StdString> CGrid::getAxisList()
499  TRY
500  {
501    setAxisList();
502    return axisList_;
503  }
504  CATCH
505
506  /*!
507  \brief Get list of id of scalar
508  \return id list of scalar
509  */
510  std::vector<StdString> CGrid::getScalarList()
511  TRY
512  {
513    setScalarList();
514    return scalarList_;
515  }
516  CATCH
517
518
519  void CGrid::computeElements(void)
520  {
521    const auto& domains = getDomains() ;
522    const auto& axis = getAxis() ;
523    const auto& scalars = getScalars() ;
524    int idxDomain = 0, idxAxis=0 , idxScalar=0 ; 
525 
526    for(auto type : order_)
527    {
528      if      (type == 0) { elements_.push_back({scalars[idxScalar], TYPE_SCALAR, scalars[idxScalar], nullptr, nullptr } ) ; idxScalar++;}
529      else if (type == 1) { elements_.push_back({axis[idxAxis], TYPE_AXIS, nullptr, axis[idxAxis], nullptr}) ; idxAxis++;}
530      else if (type == 2) { elements_.push_back({domains[idxDomain], TYPE_DOMAIN, nullptr, nullptr, domains[idxDomain] }) ; idxDomain++;}       
531    }
532    elementsComputed_ = true ;
533  }
534 
535 
536 /*!
537    Parse a grid, for now, it contains only domain, axis and scalar
538  */
539  void CGrid::parse(xml::CXMLNode& node)
540  TRY
541  {
542    SuperClass::parse(node);
543
544    if (node.goToChildElement())
545    {
546      StdString domainName("domain");
547      StdString axisName("axis");
548      StdString scalarName("scalar");
549      do
550      {
551        if (node.getElementName() == domainName) {
552          order_.push_back(2);
553          this->getVirtualDomainGroup()->parseChild(node);
554        }
555        if (node.getElementName() == axisName) {
556          order_.push_back(1);
557          this->getVirtualAxisGroup()->parseChild(node);
558        }
559        if (node.getElementName() == scalarName) {
560          order_.push_back(0);
561          this->getVirtualScalarGroup()->parseChild(node);
562        }
563      } while (node.goToNextElement());
564      node.goToParentElement();
565    }
566
567    if (!order_.empty())
568    {
569      int sizeOrd = order_.size();
570      axis_domain_order.resize(sizeOrd);
571      for (int i = 0; i < sizeOrd; ++i)
572      {
573        axis_domain_order(i) = order_[i];
574      }
575    }
576
577    setDomainList();
578    setAxisList();
579    setScalarList();
580   }
581   CATCH_DUMP_ATTR
582
583
584  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
585  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
586  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
587  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
588
589
590
591   StdSize CGrid::getDimension(void)
592   TRY
593   {
594      return getGlobalDimension().size();
595   }
596   CATCH_DUMP_ATTR
597
598   //---------------------------------------------------------------
599
600   StdSize CGrid::getDataSize(void) 
601   TRY
602   {
603     StdSize retvalue = 1;
604     if (!isScalarGrid())
605     {
606       std::vector<int> dataNindex = getClientDistribution()->getDataNIndex();
607       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];       
608     }
609     return retvalue;
610   }
611   CATCH
612   
613   /*!
614    * Get the local data grid size, ie the size of the compressed grid (inside the workflow)
615    * \return The size od the compressed grid
616    */
617    StdSize  CGrid::getLocalDataSize(void) { return getClientDistribution()->getLocalDataSize();}
618
619
620   /*!
621    * Compute the minimum buffer size required to send the attributes to the server(s).
622    *
623    * \return A map associating the server rank with its minimum buffer size.
624    * TODO: Refactor code
625    */
626   std::map<int, StdSize> CGrid::getAttributesBufferSize(CContextClient* client, bool bufferForWriting)
627   TRY
628   {
629     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
630
631     // The grid indexes require a similar size as the actual data
632     std::map<int, StdSize> dataSizes = getDataBufferSize(client, "", bufferForWriting);
633     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
634     for (it = dataSizes.begin(); it != itE; ++it)
635     {
636       it->second += 2 * sizeof(bool);
637       if (it->second > attributesSizes[it->first])
638         attributesSizes[it->first] = it->second;
639     }
640     
641     // Account for the axis attributes
642     std::vector<CAxis*> axisList = getAxis();
643     for (size_t i = 0; i < axisList.size(); ++i)
644     {
645       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client, getGlobalDimension(),getAxisPositionInGrid()[i]);
646       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
647       {
648         it->second += 2 * sizeof(bool);
649         if (it->second > attributesSizes[it->first])
650           attributesSizes[it->first] = it->second;
651       }
652     }
653
654     // Account for the domain attributes
655     std::vector<CDomain*> domList = getDomains();
656     for (size_t i = 0; i < domList.size(); ++i)
657     {
658       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize(client);
659       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
660       {
661         it->second += 2 * sizeof(bool);
662         if (it->second > attributesSizes[it->first])
663           attributesSizes[it->first] = it->second;
664       }
665     }
666
667     return attributesSizes;
668  }
669   CATCH_DUMP_ATTR
670
671   /*!
672    * Compute the minimum buffer size required to send the data.
673    * \param client contextClient used to determine the size of connected receivers
674    * \param id the id used to tag the data
675    * \param bufferForWriting flag indicating if a buffer is used to send data for writing
676    * \return A map associating the sender rank with its minimum buffer size.
677    */
678   std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/, bool bufferForWriting /*= "false"*/)
679   TRY
680   {     
681     // The record index is sometimes sent along with the data but we always
682     // include it in the size calculation for the sake of simplicity
683     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() 
684                                                       + 2 * sizeof(size_t) 
685                                                       + sizeof(size_t);
686
687     std::map<int, StdSize> dataSizes;
688     int receiverSize = client->serverSize;
689     std::map<int,size_t>& dataSizeMap = bufferForWriting ? connectedDataSize_[receiverSize]: connectedDataSizeRead_;
690     std::vector<int>& connectedServerRanks = bufferForWriting ? connectedServerRank_[receiverSize] : connectedServerRankRead_;
691
692     std::map<int, size_t>::const_iterator itEnd = dataSizeMap.end();
693     for (size_t k = 0; k < connectedServerRanks.size(); ++k)
694     {
695       int rank = connectedServerRanks[k];
696       std::map<int, size_t>::const_iterator it = dataSizeMap.find(rank);
697       size_t count = (it != itEnd) ? it->second : 0;
698
699       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
700     }
701
702     return dataSizes;
703   }
704   CATCH_DUMP_ATTR
705
706   size_t CGrid::getGlobalWrittenSize(void)
707   TRY
708   {
709         std::vector<CDomain*> domainP = this->getDomains();
710     std::vector<CAxis*> axisP = this->getAxis();
711     
712     size_t globalGridSize=1 ;
713     for (std::vector<CDomain*>::iterator it=domainP.begin(); it!=domainP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
714     for (std::vector<CAxis*>::iterator it=axisP.begin(); it!=axisP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
715     return globalGridSize ;
716   }
717   CATCH_DUMP_ATTR
718   
719
720   void CGrid::computeAxisPositionInGrid(void)
721   {
722     axisPositionInGrid_.resize(0);
723     int idx = 0;
724     for (int i = 0; i < axis_domain_order.numElements(); ++i)
725     {
726       int elementDimension = axis_domain_order(i);
727       if (1 == elementDimension)
728       {
729         axisPositionInGrid_.push_back(idx);
730         ++idx;
731       }
732       else if (2 == elementDimension) idx += 2;
733     }
734   }
735
736   void CGrid::checkAttributesAfterTransformation()
737   TRY
738   {
739      setAxisList();
740      std::vector<CAxis*> axisListP = this->getAxis();
741      for (int i = 0; i < axisListP.size(); ++i)
742        axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(), getAxisPositionInGrid()[i]);
743   
744      setDomainList();
745      std::vector<CDomain*> domListP = this->getDomains();
746      if (!domListP.empty())
747      {
748        for (int i = 0; i < domListP.size(); ++i)
749        {
750          domListP[i]->checkAttributesOnClientAfterTransformation();
751        }
752      }
753   }
754   CATCH_DUMP_ATTR
755
756   //---------------------------------------------------------------
757
758   /*!
759    * Test whether the data defined on the grid can be outputted in a compressed way.
760    *
761    * \return true if and only if a mask was defined for this grid
762    */
763   bool CGrid::isCompressible(void) const
764   TRY
765   {
766      return isCompressible_;
767   }
768   CATCH
769
770   //---------------------------------------------------------------
771
772   void CGrid::addRelFileCompressed(const StdString& filename)
773   TRY
774   {
775      this->relFilesCompressed.insert(filename);
776   }
777   CATCH_DUMP_ATTR
778
779   bool CGrid::isWrittenCompressed(const StdString& filename) const
780   TRY
781   {
782      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
783   }
784   CATCH
785
786   //---------------------------------------------------------------
787   /*
788     Find all reference of grid's components and inherite attributes if necessary
789   */
790   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
791   TRY
792   {
793     if (this->isDomainAxisChecked) return;
794
795     this->solveScalarRef(areAttributesChecked);
796     this->solveAxisRef(areAttributesChecked);
797     this->solveDomainRef(areAttributesChecked);     
798     this->isDomainAxisChecked = areAttributesChecked;
799   }
800   CATCH_DUMP_ATTR
801
802   /*
803     Go up hierachy reference and fill in the base reference with attributes of the children
804     This function should be only used after reading component's attributes from file
805   */
806   void CGrid::solveDomainAxisBaseRef()
807   TRY
808   {
809     if (this->hasDomainAxisBaseRef_) return;
810     // Account for the scalar attributes
811     std::vector<CScalar*> scalarList = getScalars();
812     for (size_t i = 0; i < scalarList.size(); ++i)
813     {
814       scalarList[i]->setAttributesReference();
815     }
816
817     // Account for the axis attributes
818     std::vector<CAxis*> axisList = getAxis();
819     for (size_t i = 0; i < axisList.size(); ++i)
820     {
821       axisList[i]->setAttributesReference();
822     }
823
824     // Account for the domain attributes
825     std::vector<CDomain*> domList = getDomains();
826     for (size_t i = 0; i < domList.size(); ++i)
827     {
828       domList[i]->setAttributesReference();
829     }
830
831     this->hasDomainAxisBaseRef_ = true;
832   }
833   CATCH_DUMP_ATTR
834
835   void CGrid::checkEligibilityForCompressedOutput()
836   TRY
837   {
838     // We don't check if the mask is valid here, just if a mask has been defined at this point.
839     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
840   }
841   CATCH_DUMP_ATTR
842
843   //ym obsolete -> to be removed later
844   void CGrid::checkMaskIndex(bool doSendingIndex)
845   TRY
846   {
847     CContext* context = CContext::getCurrent();
848     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)     
849     {
850       if (this->isChecked && doSendingIndex && !isIndexSent) 
851       { 
852         if (isScalarGrid())  /*sendIndexScalarGrid()*/;
853         else  /*sendIndex()*/;
854         this->isIndexSent = true; 
855       }
856     }
857
858     if (this->isChecked) return;
859     this->checkAttributesAfterTransformation();
860
861     // TODO: Transfer grid attributes
862     //if (!context->hasClient && context->hasServer) this->createMask();
863     this->computeIndex();
864
865     if (!(this->hasTransform() && !this->isTransformed()))
866      this->isChecked = true;
867
868     if (!(this->hasTransform() && (!this->isGenerated())))
869      this->isChecked = true;
870   }
871   CATCH_DUMP_ATTR
872
873
874   bool CGrid::hasMask() const
875   TRY
876   {
877     return (!mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty() ||
878             !mask_4d.isEmpty() || !mask_5d.isEmpty() || !mask_6d.isEmpty() || !mask_7d.isEmpty());
879   }
880   CATCH
881
882   
883   CArray<bool,1>& CGrid::getMask(void)
884   {
885     
886      if (mask_.isEmpty())
887      { 
888        if (!mask_0d.isEmpty()) mask_.reference(CArray<bool,1>(mask_0d.dataFirst(),shape(mask_0d.numElements()), neverDeleteData)) ;
889        if (!mask_1d.isEmpty()) mask_.reference(CArray<bool,1>(mask_1d.dataFirst(),shape(mask_1d.numElements()), neverDeleteData)) ;
890        if (!mask_2d.isEmpty()) mask_.reference(CArray<bool,1>(mask_2d.dataFirst(),shape(mask_2d.numElements()), neverDeleteData)) ;
891        if (!mask_3d.isEmpty()) mask_.reference(CArray<bool,1>(mask_3d.dataFirst(),shape(mask_3d.numElements()), neverDeleteData)) ;
892        if (!mask_4d.isEmpty()) mask_.reference(CArray<bool,1>(mask_4d.dataFirst(),shape(mask_4d.numElements()), neverDeleteData)) ;
893        if (!mask_5d.isEmpty()) mask_.reference(CArray<bool,1>(mask_5d.dataFirst(),shape(mask_5d.numElements()), neverDeleteData)) ;
894        if (!mask_6d.isEmpty()) mask_.reference(CArray<bool,1>(mask_6d.dataFirst(),shape(mask_6d.numElements()), neverDeleteData)) ;
895        if (!mask_7d.isEmpty()) mask_.reference(CArray<bool,1>(mask_7d.dataFirst(),shape(mask_7d.numElements()), neverDeleteData)) ;
896      }
897      return mask_ ;
898   }
899   /*
900     Create mask of grid from mask of its components
901   */
902   void CGrid::createMask(void)
903   TRY
904   {
905      using namespace std;
906      std::vector<CDomain*> domainP = this->getDomains();
907      std::vector<CAxis*> axisP = this->getAxis();
908      int dim = domainP.size() * 2 + axisP.size();
909
910      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
911      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask);
912      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
913      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
914
915      switch (dim) {
916        case 1:
917          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
918          break;
919        case 2:
920          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
921          break;
922        case 3:
923          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
924          break;
925        case 4:
926          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true);
927          break;
928        case 5:
929          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true);
930          break;
931        case 6:
932          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true);
933          break;
934        case 7:
935          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true);
936          break;
937        default:
938          break;
939      }
940   }
941   CATCH_DUMP_ATTR
942
943   /*
944     Check validity of grid's mask by using the masks of its components
945   */
946   void CGrid::checkMask(void)
947   TRY
948   {
949      using namespace std;
950      std::vector<CDomain*> domainP = this->getDomains();
951      std::vector<CAxis*> axisP = this->getAxis();
952      int dim = domainP.size() * 2 + axisP.size();
953
954      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
955      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask);
956      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
957      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
958
959      switch (dim) {
960        case 1:
961          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
962          break;
963        case 2:
964          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
965          break;
966        case 3:
967          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
968          break;
969        case 4:
970          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order);
971          break;
972        case 5:
973          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order);
974          break;
975        case 6:
976          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order);
977          break;
978        case 7:
979          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order);
980          break;
981        default:
982          break;
983      }
984   }
985   CATCH_DUMP_ATTR
986
987   /*
988     Modify value of mask in a certain index
989     This function can be used to correct the mask of grid after being constructed with createMask
990     \param [in] indexToModify
991     \param [in] modifyValue
992   */
993   void CGrid::modifyMask(const CArray<int,1>& indexToModify, bool modifyValue)
994   TRY
995   {
996      using namespace std;
997      std::vector<CDomain*> domainP = this->getDomains();
998      std::vector<CAxis*> axisP = this->getAxis();
999      int dim = domainP.size() * 2 + axisP.size();
1000
1001      switch (dim) {
1002        case 0:
1003          modifyGridMask(mask_0d, indexToModify, modifyValue);
1004          break;
1005        case 1:
1006          modifyGridMask(mask_1d, indexToModify, modifyValue);
1007          break;
1008        case 2:
1009          modifyGridMask(mask_2d, indexToModify, modifyValue);
1010          break;
1011        case 3:
1012          modifyGridMask(mask_3d, indexToModify, modifyValue);
1013          break;
1014        case 4:
1015          modifyGridMask(mask_4d, indexToModify, modifyValue);
1016          break;
1017        case 5:
1018          modifyGridMask(mask_5d, indexToModify, modifyValue);
1019          break;
1020        case 6:
1021          modifyGridMask(mask_6d, indexToModify, modifyValue);
1022          break;
1023        case 7:
1024          modifyGridMask(mask_7d, indexToModify, modifyValue);
1025          break;
1026        default:
1027          break;
1028      }
1029   }
1030   CATCH_DUMP_ATTR
1031
1032   /*
1033     Change the mask size. This function is used on reconstructing mask in server side
1034     \param [in] newDimensionSize
1035     \param [in] newValue
1036   */
1037   void CGrid::modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue)
1038   TRY
1039   {     
1040      std::vector<CDomain*> domainP = this->getDomains();
1041      std::vector<CAxis*> axisP = this->getAxis();           
1042      int dim = domainP.size() * 2 + axisP.size();
1043
1044      switch (dim) {
1045        case 0:
1046          modifyGridMaskSize(mask_0d, newDimensionSize, newValue);
1047          break;
1048        case 1:
1049          modifyGridMaskSize(mask_1d, newDimensionSize, newValue);
1050          break;
1051        case 2:
1052          modifyGridMaskSize(mask_2d, newDimensionSize, newValue);
1053          break;
1054        case 3:
1055          modifyGridMaskSize(mask_3d, newDimensionSize, newValue);
1056          break;
1057        case 4:
1058          modifyGridMaskSize(mask_4d, newDimensionSize, newValue);
1059          break;
1060        case 5:
1061          modifyGridMaskSize(mask_5d, newDimensionSize, newValue);
1062          break;
1063        case 6:
1064          modifyGridMaskSize(mask_6d, newDimensionSize, newValue);
1065          break;
1066        case 7:
1067          modifyGridMaskSize(mask_7d, newDimensionSize, newValue);
1068          break;
1069        default:
1070          break;
1071      }
1072   }
1073   CATCH_DUMP_ATTR
1074
1075   //---------------------------------------------------------------
1076
1077   void CGrid::solveDomainRef(bool sendAtt)
1078   TRY
1079   {
1080      setDomainList();
1081      std::vector<CDomain*> domListP = this->getDomains();
1082      if (!domListP.empty())
1083      {
1084        for (int i = 0; i < domListP.size(); ++i)
1085        {
1086          if (sendAtt) domListP[i]->sendCheckedAttributes();
1087          else domListP[i]->checkAttributesOnClient();
1088        }
1089      }
1090   }
1091   CATCH_DUMP_ATTR
1092
1093   //---------------------------------------------------------------
1094
1095   void CGrid::solveAxisRef(bool sendAtt)
1096   TRY
1097   {
1098      setAxisList();
1099      std::vector<CAxis*> axisListP = this->getAxis();
1100      if (!axisListP.empty())
1101      {
1102        for (int i = 0; i < axisListP.size(); ++i)
1103        {
1104          if (sendAtt)
1105            axisListP[i]->sendCheckedAttributes(getGlobalDimension(),getAxisPositionInGrid()[i]);
1106          else
1107            axisListP[i]->checkAttributesOnClient();
1108        }
1109      }
1110   }
1111   CATCH_DUMP_ATTR
1112
1113   //---------------------------------------------------------------
1114
1115   void CGrid::solveScalarRef(bool sendAtt)
1116   TRY
1117   {
1118      setScalarList();
1119      std::vector<CScalar*> scalarListP = this->getScalars();
1120      if (!scalarListP.empty())
1121      {
1122        for (int i = 0; i < scalarListP.size(); ++i)
1123        {
1124          /*Nothing to do for now */
1125//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
1126//          else scalarListP[i]->checkAttributesOnClient();
1127        }
1128      }
1129   }
1130   CATCH_DUMP_ATTR
1131
1132   /*!
1133      Compute the index to for write data into a file
1134   */
1135   void CGrid::computeWrittenIndex()
1136   TRY
1137   {     
1138      if (computedWrittenIndex_) return;
1139      computedWrittenIndex_ = true;
1140
1141      if (isScalarGrid())
1142      {
1143        size_t nbWritten = 1;
1144        int writtenIndex = 0;
1145
1146        localIndexToWriteOnClient_.resize(nbWritten); 
1147        localIndexToWriteOnServer_.resize(nbWritten);
1148        localIndexToWriteOnServer_(0) = writtenIndex;
1149        localIndexToWriteOnClient_(0) = writtenIndex;
1150       
1151        return;
1152      }
1153
1154      size_t nbWritten = 0, indGlo;
1155      CDistributionClient::GlobalLocalDataMap& globalDataIndex = getClientDistribution()->getGlobalDataIndexOnClient();
1156      CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(),
1157                                                              ite = globalDataIndex.end(), it;   
1158      const CDistributionServer::GlobalLocalMap& globalLocalIndex = serverDistribution_->getGlobalLocalIndex();                                                             
1159      CDistributionServer::GlobalLocalMap::const_iterator itSrvb = globalLocalIndex.begin(),
1160                                                          itSrve = globalLocalIndex.end(), itSrv;
1161      for (it = itb; it != ite; ++it)
1162      {
1163        indGlo = it->first;
1164        if (globalLocalIndex.end() != globalLocalIndex.find(indGlo)) ++nbWritten;               
1165      }
1166
1167      localIndexToWriteOnClient_.resize(nbWritten); 
1168      localIndexToWriteOnServer_.resize(nbWritten);
1169     
1170      {
1171        numberWrittenIndexes_ = nbWritten;
1172        if (isDataDistributed())
1173        {
1174          CContext* context = CContext::getCurrent();     
1175          MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, context->intraComm_);
1176          MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, context->intraComm_);
1177          offsetWrittenIndexes_ -= numberWrittenIndexes_;
1178        }
1179        else
1180          totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1181      }
1182
1183      nbWritten = 0; 
1184      for (it = itb; it != ite; ++it)
1185      {
1186        indGlo = it->first;
1187        itSrv = globalLocalIndex.find(indGlo);
1188        if (itSrve != itSrv)
1189        {
1190          localIndexToWriteOnServer_(nbWritten) = itSrv->second;
1191          localIndexToWriteOnClient_(nbWritten) = it->second;
1192          ++nbWritten;               
1193        } 
1194      }
1195   }
1196   CATCH_DUMP_ATTR
1197
1198   
1199
1200   /*!
1201     Compute the global index of grid to send to server as well as the connected server of the current client.
1202     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
1203     their global index. We can have a map of global index of grid and local index that each client holds
1204     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
1205     of the current client.
1206   */
1207   void CGrid::computeGridIndexToFileServer(CContextClient* client)
1208   {
1209     if (isScalarGrid()) computeConnectedClientsScalarGrid(client);
1210     else computeConnectedClients(client);
1211   
1212     // compute indices for client/server transfer for domain
1213     for (const auto& domainId : domList_) CDomain::get(domainId)->computeConnectedClients(client);
1214   
1215   
1216     // compute indices for client/server transfer for axis
1217     std::vector<CAxis*> axisList = this->getAxis();
1218     for(int i=0 ; i<axisList.size(); i++) axisList[i] -> computeConnectedClients(client, getGlobalDimension(),getAxisPositionInGrid()[i]) ;
1219   }
1220   //---------------------------------------------------------------
1221
1222   
1223   void CGrid::computeClientDistribution(void)
1224   {
1225     if (computeClientDistribution_done_) return ;
1226     else computeClientDistribution_done_ = true ;
1227
1228     CContext* context = CContext::getCurrent();
1229     int rank = context-> getIntraCommRank();
1230     clientDistribution_ = new CDistributionClient(rank, this);
1231   }
1232
1233   void CGrid::computeStoreIndex_client(void)
1234   {
1235     if (computeStoreIndex_client_done_) return ;
1236     else computeStoreIndex_client_done_ = true ;
1237     if (isScalarGrid())
1238     {
1239       storeIndex_client_.resize(1);
1240       storeIndex_client_(0) = 0;
1241     }
1242     else
1243     {
1244       CDistributionClient* clientDistribution = getClientDistribution() ;
1245       const std::vector<int>& localDataIndex = clientDistribution->getLocalDataIndexOnClient() ;
1246       int nbStoreIndex = localDataIndex.size() ;
1247       storeIndex_client_.resize(nbStoreIndex);
1248       for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = localDataIndex[idx];
1249     }
1250   }
1251
1252   void CGrid::computeStoreMask_client(void)
1253   {
1254     if (computeStoreMask_client_done_) return ;
1255     else computeStoreMask_client_done_ = true ;
1256     if (isScalarGrid())
1257     {
1258       storeMask_client_.resize(1);
1259       storeMask_client_(0) = true;
1260     }
1261     else
1262     {
1263       CDistributionClient* clientDistribution = getClientDistribution() ;
1264       const std::vector<bool>& localMaskIndex = clientDistribution->getLocalMaskIndexOnClient() ;
1265       int nbMaskIndex = localMaskIndex.size() ;
1266       storeMask_client_.resize(nbMaskIndex);
1267       for (int idx = 0; idx < nbMaskIndex; ++idx) storeMask_client_(idx) = localMaskIndex[idx];
1268     }
1269   }
1270
1271
1272  void CGrid::computeOutLocalIndexStoreOnClient(void)
1273  {
1274    if (computeOutLocalIndexStoreOnClient_done_) return ;
1275    else computeOutLocalIndexStoreOnClient_done_=true ;
1276
1277    if (isScalarGrid())
1278    {
1279        auto& outGlobalIndexFromClient  = getOutGlobalIndexFromClient();
1280        auto itb = outGlobalIndexFromClient.begin(), ite = outGlobalIndexFromClient.end() ;
1281        for (auto it = itb; it != ite; ++it)
1282        {
1283          int rank = it->first;
1284          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1285          outLocalIndexStoreOnClient_.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1286          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient_[rank];
1287          if (1 != globalIndex.numElements())
1288            ERROR("void CGrid::computeClientIndexScalarGrid()",
1289              << "Something wrong happened. "
1290              << "Number of received global index on scalar grid should equal to 1" 
1291              << "Number of received global index " << globalIndex.numElements() << ".");
1292
1293          localIndex(0) = globalIndex(0);
1294        }
1295    }
1296    else
1297    {
1298      CDistributionClient::GlobalLocalDataMap& globalDataIndex = getClientDistribution()->getGlobalDataIndexOnClient();
1299      CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
1300      auto& outGlobalIndexFromClient  = getOutGlobalIndexFromClient();
1301      auto itb = outGlobalIndexFromClient.begin(), ite = outGlobalIndexFromClient.end() ;
1302   
1303      for (auto it = itb; it != ite; ++it)
1304      {
1305         int rank = it->first;
1306         CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1307         outLocalIndexStoreOnClient_.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1308         CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient_[rank];
1309         size_t nbIndex = 0;
1310
1311        // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
1312        for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
1313          if (itGloe != globalDataIndex.find(globalIndex(idx))) ++nbIndex;
1314
1315        if (nbIndex != localIndex.numElements())
1316             ERROR("void CGrid::computeClientIndex()",
1317                 << "Number of local index on client is different from number of received global index"
1318                 << "Rank of sent client " << rank <<"."
1319                 << "Number of local index " << nbIndex << ". "
1320                 << "Number of received global index " << localIndex.numElements() << ".");
1321
1322        nbIndex = 0;
1323        for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
1324          if (itGloe != globalDataIndex.find(globalIndex(idx)))
1325            localIndex(idx) = globalDataIndex[globalIndex(idx)];
1326      }
1327    }
1328  }
1329
1330  bool CGrid::isDataDistributed(void) 
1331  { 
1332    return getClientDistribution()->isDataDistributed() ;
1333  }
1334
1335   /*!
1336     Compute connected receivers and indexes to be sent to these receivers.
1337   */
1338   void CGrid::computeConnectedClients(CContextClient* client)
1339   TRY
1340   {
1341     if (computeConnectedClients_done_.count(client)!=0) return ;
1342     else  computeConnectedClients_done_.insert(client) ;
1343
1344     CContext* context = CContext::getCurrent();
1345     
1346     set<int> listReceiverSize ;
1347     int receiverSize = client->serverSize;
1348     
1349     if (listReceiverSize.find(receiverSize)==listReceiverSize.end())
1350     {
1351       listReceiverSize.insert(receiverSize) ;
1352       if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end())
1353       {
1354          // delete corresponding map in case of recompute, probably because a grid could has been modifiedd
1355          // by a transformation
1356          connectedServerRank_.erase(receiverSize);
1357          connectedDataSize_.erase(receiverSize);
1358          globalIndexOnServer_.erase(receiverSize);
1359          nbSenders_.erase(receiverSize);
1360       }
1361
1362       if (!doGridHaveDataDistributed(client))
1363       {
1364          if (client->isServerLeader())
1365          {
1366            size_t ssize = getClientDistribution()->getLocalDataIndexOnClient().size();
1367            const std::list<int>& ranks = client->getRanksServerLeader();
1368            for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1369            {
1370              connectedServerRank_[receiverSize].push_back(*itRank);
1371              connectedDataSize_[receiverSize][*itRank] = ssize;
1372            }
1373          }
1374          return;
1375       }
1376
1377       // Compute mapping between client and server
1378       std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
1379       CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
1380       std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
1381                                                                                                    client->clientRank,
1382                                                                                                    client->clientSize,
1383                                                                                                    axis_domain_order,
1384                                                                                                    getDistributedDimension());
1385
1386       // Even if servers have no index, they must received something from client
1387       // We only use several client to send "empty" message to these servers
1388       std::list<int> serverZeroIndexLeader;
1389       std::list<int> serverZeroIndexNotLeader;
1390       CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
1391       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
1392         *it = serverZeroIndex[*it];
1393
1394       if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end())
1395         computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]);
1396
1397       const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getClientDistribution()->getGlobalLocalDataSendToServer();
1398       CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
1399       CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
1400       itbGlobalMap = globalIndexOnServer_[receiverSize].begin();
1401       iteGlobalMap = globalIndexOnServer_[receiverSize].end();
1402
1403       for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1404       {
1405         int serverRank = itGlobalMap->first;
1406         int indexSize = itGlobalMap->second.size();
1407         const std::vector<size_t>& indexVec = itGlobalMap->second;
1408         for (int idx = 0; idx < indexSize; ++idx)
1409         {
1410            itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
1411            if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
1412            {
1413              if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank))
1414                connectedDataSize_[receiverSize][serverRank] = 1;
1415              else
1416                ++connectedDataSize_[receiverSize][serverRank];
1417            }
1418         }
1419       }
1420
1421       // Connected servers which really have index
1422       for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 
1423         connectedServerRank_[receiverSize].push_back(itGlobalMap->first);
1424     
1425       // Connected servers which have no index at all
1426       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
1427         connectedServerRank_[receiverSize].push_back(*it);
1428
1429       // Even if a client has no index, it must connect to at least one server and
1430       // send an "empty" data to this server
1431       if (connectedServerRank_[receiverSize].empty())
1432         connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);
1433 
1434       // Now check if all servers have data to receive. If not, master client will send empty data.
1435       // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive.
1436       std::vector<int> counts (client->clientSize);
1437       std::vector<int> displs (client->clientSize);
1438       displs[0] = 0;
1439       int localCount = connectedServerRank_[receiverSize].size() ;
1440       MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ;
1441       for (int i = 0; i < client->clientSize-1; ++i) displs[i+1] = displs[i] + counts[i];
1442       std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]);
1443       MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm);
1444
1445       if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0))
1446       {
1447         std::vector<bool> isSrvConnected (receiverSize, false);
1448         for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true;
1449         for (int i = 0; i < receiverSize; ++i) if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i);
1450       }
1451
1452       nbSenders_[receiverSize] = CClientServerMapping::computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);
1453     }
1454   }
1455   CATCH_DUMP_ATTR
1456
1457   /*!
1458     Compute the global index of grid to send to server as well as the connected server of the current client.
1459     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
1460     their global index. We can have a map of global index of grid and local index that each client holds
1461     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
1462     of the current client.
1463   */
1464   // ym obsolete : to be removed....
1465   void CGrid::computeIndex(void)
1466   TRY
1467   {
1468    // old interface
1469     CContext* context = CContext::getCurrent();
1470     if (isScalarGrid())
1471     {
1472       //computeClientIndexScalarGrid();
1473       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)
1474       {
1475         // ym computeConnectedClientsScalarGrid();
1476       }
1477     }
1478     else
1479     {
1480       //computeClientIndex();
1481       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)
1482       {
1483         //computeConnectedClients();
1484       }
1485     }
1486//ym     if (CServer::serverLevel==2)
1487     if (context->getServiceType()==CServicesManager::OUT_SERVER)
1488     {
1489       computeWrittenIndex() ;
1490       if (serverDistribution_!=0) serverDistribution_->partialClear() ;
1491       if (clientDistribution_!=0) clientDistribution_->partialClear() ;
1492       outGlobalIndexFromClient_.clear() ;
1493     }
1494   }
1495   CATCH_DUMP_ATTR
1496
1497   /*!
1498      Compute the global of (client) grid to send to server with the global index of each element of grid
1499      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
1500      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
1501      on each element whose size is much smaller than one of whole grid.
1502      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
1503      \param [in] client contextClient
1504      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
1505   */
1506   void CGrid::computeIndexByElement(const std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
1507                                     const CContextClient* client,
1508                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
1509   TRY
1510   {
1511     int serverSize = client->serverSize;
1512
1513     std::vector<CDomain*> domList = getDomains();
1514     std::vector<CAxis*> axisList = getAxis();
1515
1516     // Some pre-calculations of global index on each element of current grid.
1517     int nbElement = axis_domain_order.numElements();
1518     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
1519     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
1520     std::vector<size_t> elementNGlobal(nbElement);
1521     elementNGlobal[0] = 1;
1522     size_t globalSize = 1;
1523     for (int idx = 0; idx < nbElement; ++idx)
1524     {
1525       elementNGlobal[idx] = globalSize;
1526       size_t elementSize;
1527       size_t elementGlobalSize = 1;
1528       if (2 == axis_domain_order(idx)) // This is domain
1529       {
1530         elementSize = domList[domainIdx]->i_index.numElements();
1531         globalIndexElement[idx].resize(elementSize);
1532         for (int jdx = 0; jdx < elementSize; ++jdx)
1533         {
1534           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
1535         }
1536         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
1537         ++domainIdx;
1538       }
1539       else if (1 == axis_domain_order(idx))  // This is axis
1540       {
1541         elementSize = axisList[axisIdx]->index.numElements();
1542         globalIndexElement[idx].resize(elementSize);
1543         for (int jdx = 0; jdx < elementSize; ++jdx)
1544         {
1545           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
1546         }
1547         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
1548         ++axisIdx;
1549       }
1550       else  // Of course, this is scalar
1551       {
1552         globalIndexElement[idx].resize(1);
1553         globalIndexElement[idx](0) = 0;
1554         elementGlobalSize = 1;
1555       }
1556       globalSize *= elementGlobalSize;
1557     }
1558
1559     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
1560     std::vector<std::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
1561     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
1562     // Number of temporary distributed global index held by each client for each server
1563     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
1564     CArray<int,1> nbIndexOnServerTmp(serverSize);
1565     for (int idx = 0; idx < nbElement; ++idx)
1566     {
1567       nbIndexOnServer = 0;
1568       const std::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
1569       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
1570       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
1571       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
1572       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
1573       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
1574                                                                    ite = globalIndexElementOnServerMap.end(), it;
1575       for (it = itb; it != ite; ++it)
1576       {
1577         const std::vector<int>& tmp = it->second;
1578         nbIndexOnServerTmp = 0;
1579         for (int i = 0; i < tmp.size(); ++i)
1580         {
1581           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
1582         }
1583         nbIndexOnServer += nbIndexOnServerTmp;
1584       }
1585
1586       for (int i = 0; i < serverSize; ++i)
1587       {
1588         if (0 != nbIndexOnServer(i))
1589         {
1590           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
1591           elementOnServer[idx][i] = true;
1592         }
1593       }
1594
1595     nbIndexOnServer = 0;
1596     for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
1597     {
1598       it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
1599       if (it != ite)
1600       {
1601         const std::vector<int>& tmp = it->second;
1602         nbIndexOnServerTmp = 0;
1603         for (int i = 0; i < tmp.size(); ++i)
1604         {
1605           if (0 == nbIndexOnServerTmp(tmp[i]))
1606           {
1607             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
1608             ++nbIndexOnServerTmp(tmp[i]);
1609           }
1610         }
1611         nbIndexOnServer += nbIndexOnServerTmp;
1612       }
1613     }
1614   }
1615
1616    // Determine server which contain global source index
1617    std::vector<bool> intersectedProc(serverSize, true);
1618    for (int idx = 0; idx < nbElement; ++idx)
1619    {
1620      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
1621                     intersectedProc.begin(), intersectedProc.begin(),
1622                     std::logical_and<bool>());
1623    }
1624
1625    std::vector<int> srcRank;
1626    for (int idx = 0; idx < serverSize; ++idx)
1627    {
1628      if (intersectedProc[idx]) srcRank.push_back(idx);
1629    }
1630
1631    // Compute the global index of grid from global index of each element.
1632    for (int i = 0; i < srcRank.size(); ++i)
1633    {
1634      size_t ssize = 1;
1635      int rankSrc = srcRank[i];
1636      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
1637      std::vector<size_t> currentIndex(nbElement,0);
1638      for (int idx = 0; idx < nbElement; ++idx)
1639      {
1640        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
1641        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
1642      }
1643      globalIndexOnServer[rankSrc].resize(ssize);
1644
1645      std::vector<int> idxLoop(nbElement,0);
1646      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
1647      size_t idx = 0;
1648      while (idx < ssize)
1649      {
1650        for (int ind = 0; ind < nbElement; ++ind)
1651        {
1652          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
1653          {
1654            idxLoop[ind] = 0;
1655            ++idxLoop[ind+1];
1656          }
1657
1658          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
1659        }
1660
1661        for (int ind = 0; ind < innnerLoopSize; ++ind)
1662        {
1663          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
1664          size_t globalSrcIndex = 0;
1665          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
1666          {
1667            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
1668          }
1669          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
1670          ++idx;
1671          ++idxLoop[0];
1672        }
1673      }
1674    }
1675   }
1676   CATCH_DUMP_ATTR
1677//----------------------------------------------------------------
1678
1679
1680
1681   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
1682   TRY
1683   {
1684     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
1685     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
1686     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
1687
1688     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
1689     {
1690       CDomain* domain = CDomain::createDomain();
1691       domain->duplicateAttributes(domainSrcTmp[idx]);
1692       domain->duplicateTransformation(domainSrcTmp[idx]);
1693       domain->solveRefInheritance(true);
1694       domain->solveInheritanceTransformation();
1695       domainSrc.push_back(domain);
1696     }
1697
1698     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
1699     {
1700       CAxis* axis = CAxis::createAxis();
1701       axis->duplicateAttributes(axisSrcTmp[idx]);
1702       axis->duplicateTransformation(axisSrcTmp[idx]);
1703       axis->solveRefInheritance(true);
1704       axis->solveInheritanceTransformation();
1705       axisSrc.push_back(axis);
1706     }
1707
1708     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
1709     {
1710       CScalar* scalar = CScalar::createScalar();
1711       scalar->duplicateAttributes(scalarSrcTmp[idx]);
1712       scalar->duplicateTransformation(scalarSrcTmp[idx]);
1713       scalar->solveRefInheritance(true);
1714       scalar->solveInheritanceTransformation();
1715       scalarSrc.push_back(scalar);
1716     }
1717
1718      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
1719
1720      return grid;
1721   }
1722   CATCH
1723
1724   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1725                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1726   TRY
1727   {
1728      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1729        ERROR("CGrid* CGrid::generateId(...)",
1730              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1731              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1732
1733      std::ostringstream id;
1734
1735      if (domains.empty() && axis.empty() && !scalars.empty())
1736        id << "__scalar_";
1737
1738      if (0 != (domains.size() + axis.size() + scalars.size()))
1739      {
1740        id << "__grid";
1741
1742        if (0 == axisDomainOrder.numElements())
1743        {
1744          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
1745          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
1746          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
1747        }
1748        else
1749        {
1750          size_t iDomain = 0, iAxis = 0, iScalar = 0;
1751          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
1752          {
1753            if (2 == axisDomainOrder(i))
1754              id << "_" << domains[iDomain++]->getId();
1755            else if (1 == axisDomainOrder(i))
1756              id << "_" << axis[iAxis++]->getId();
1757            else
1758              id << "_" << scalars[iScalar++]->getId();
1759          }
1760        }
1761
1762        id << "__";
1763      }
1764
1765      return id.str();
1766   }
1767   CATCH
1768
1769   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
1770   TRY
1771   {
1772     StdString idSrc  = gridSrc->getId();
1773     StdString idDest = gridDest->getId();
1774
1775     std::ostringstream id;
1776     id << idSrc << "__" << idDest;
1777
1778     return id.str();
1779   }
1780   CATCH
1781
1782
1783   //----------------------------------------------------------------
1784
1785   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) 
1786   TRY
1787   {
1788      auto& storeIndex_client = getStoreIndex_client() ;
1789      const StdSize size = storeIndex_client.numElements();
1790
1791      stored.resize(size);
1792      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1793   }
1794   CATCH
1795
1796   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) 
1797   TRY
1798   {
1799      auto& storeIndex_client=getStoreIndex_client() ;
1800      const StdSize size = storeIndex_client.numElements();
1801
1802      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
1803   }
1804   CATCH
1805
1806   void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored) 
1807   {
1808      auto& storeIndex_client=getStoreIndex_client() ;
1809      auto& storeMask_client=getStoreMask_client() ;
1810       
1811      const StdSize size = storeIndex_client.numElements();
1812      stored.resize(size);
1813      const double nanValue = std::numeric_limits<double>::quiet_NaN();
1814
1815      if (storeMask_client.numElements() != 0)
1816        for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client(i)) ? data[storeIndex_client(i)] : nanValue;
1817      else
1818        for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1819   }
1820
1821   void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) 
1822   TRY
1823   {
1824      const std::vector<int>& localMaskedDataIndex = getClientDistribution()->getLocalMaskedDataIndexOnClient();
1825      const int size = localMaskedDataIndex.size();
1826      for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i];
1827   }
1828   CATCH
1829
1830 
1831  void CGrid::computeConnectedClientsScalarGrid(CContextClient* client)
1832  TRY
1833  {
1834    if (computeConnectedClientsScalarGrid_done_.count(client)!=0) return ;
1835
1836    CContext* context = CContext::getCurrent();
1837     
1838    set<int> listReceiverSize ;
1839
1840    int receiverSize = client->serverSize;
1841     
1842    if (listReceiverSize.find(receiverSize)==listReceiverSize.end())
1843    {
1844      listReceiverSize.insert(receiverSize) ;
1845      if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end())
1846      {
1847         // delete corresponding map in case of recompute, probably because a grid could has been modifiedd
1848         // by a transformation
1849        connectedServerRank_.erase(receiverSize);
1850        connectedDataSize_.erase(receiverSize);
1851        globalIndexOnServer_.erase(receiverSize);
1852        nbSenders_.erase(receiverSize);
1853      }
1854
1855      if (client->isServerLeader())
1856      {
1857        const std::list<int>& ranks = client->getRanksServerLeader();
1858        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1859        {
1860          int rank = *itRank;
1861          int nb = 1;
1862          connectedServerRank_[receiverSize].push_back(rank);
1863          connectedDataSize_[receiverSize][rank] = nb;
1864          nbSenders_[receiverSize][rank] = nb;
1865        }
1866      }
1867      else
1868      {
1869        const std::list<int>& ranks = client->getRanksServerNotLeader();
1870        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1871        {
1872          int rank = *itRank;
1873          int nb = 1;
1874          connectedServerRank_[receiverSize].push_back(rank);
1875          connectedDataSize_[receiverSize][rank] = nb;
1876          nbSenders_[receiverSize][rank] = nb;
1877        }
1878      }
1879    }
1880   
1881    computeConnectedClientsScalarGrid_done_.insert(client) ;
1882  }
1883  CATCH_DUMP_ATTR
1884
1885  void CGrid::sendIndexScalarGrid(CContextClient* client, const string& gridId)
1886  TRY
1887  {
1888    if (sendIndexScalarGrid_done_.count(client)!=0) return ;
1889    else sendIndexScalarGrid_done_.insert(client) ;
1890
1891    CContext* context = CContext::getCurrent();
1892   
1893    string serverGridId = gridId.empty() ? serverGridId=this->getId() : serverGridId=gridId ;
1894
1895    int receiverSize = client->serverSize;
1896
1897    CEventClient event(getType(), EVENT_ID_INDEX);
1898    list<CMessage> listMsg;
1899    list<CArray<size_t,1> > listOutIndex;
1900
1901    if (client->isServerLeader())
1902    {
1903      const std::list<int>& ranks = client->getRanksServerLeader();
1904      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1905      {
1906        int rank = *itRank;
1907        int nb = 1;
1908        storeIndex_toSrv_[client].insert(std::make_pair(rank, CArray<int,1>(nb)));
1909        listOutIndex.push_back(CArray<size_t,1>(nb));
1910
1911        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv_[client][rank];
1912        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1913
1914        for (int k = 0; k < nb; ++k)
1915        {
1916          outGlobalIndexOnServer(k) = 0;
1917          outLocalIndexToServer(k)  = 0;
1918        }
1919
1920        if (context->getServiceType()==CServicesManager::CLIENT)  // -> what about for coupling probably unusefull to be check
1921          storeIndex_fromSrv_.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1922
1923        listMsg.push_back(CMessage());
1924        listMsg.back() << serverGridId << isCompressible_ << listOutIndex.back();
1925
1926        event.push(rank, 1, listMsg.back());
1927      }
1928      client->sendEvent(event);
1929    }
1930    else
1931    {
1932      const std::list<int>& ranks = client->getRanksServerNotLeader();
1933      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1934      {
1935        int rank = *itRank;
1936        int nb = 1;         
1937        CArray<int, 1> outLocalIndexToServer(nb);
1938        for (int k = 0; k < nb; ++k)
1939        {
1940          outLocalIndexToServer(k)  = 0;
1941        }
1942
1943        if (context->getServiceType()==CServicesManager::CLIENT)
1944          storeIndex_fromSrv_.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1945      }
1946      client->sendEvent(event);
1947    }
1948  }
1949  CATCH_DUMP_ATTR
1950
1951  void CGrid::sendIndex(CContextClient* client, const string& gridId)
1952  TRY
1953  {
1954    if (sendIndex_done_.count(client)!=0) return ;
1955    else sendIndex_done_.insert(client) ;
1956    CContext* context = CContext::getCurrent();
1957    string serverGridId = gridId.empty() ? this->getId() : gridId ;
1958
1959
1960
1961    int receiverSize = client->serverSize;
1962
1963    CEventClient event(getType(), EVENT_ID_INDEX);
1964    int rank;
1965    list<CMessage> listMsg;
1966    list<CArray<size_t,1> > listOutIndex;
1967    const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getClientDistribution()->getGlobalLocalDataSendToServer();
1968    CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex,
1969                                                            iteIndex = globalLocalIndexSendToServer.end();
1970    itIndex = itbIndex;                                                             
1971
1972    if (!doGridHaveDataDistributed(client))
1973    {
1974      if (client->isServerLeader())
1975      {
1976        int indexSize = globalLocalIndexSendToServer.size();
1977        CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1978        CArray<int,1> outLocalIndexToServer(indexSize);
1979        for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1980        {
1981          outGlobalIndexOnServer(idx) = itIndex->first;
1982          outLocalIndexToServer(idx) = itIndex->second;
1983        }
1984
1985        const std::list<int>& ranks = client->getRanksServerLeader();
1986        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1987        {
1988          storeIndex_toSrv_[client].insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1989          if (context->getServiceType()==CServicesManager::CLIENT)  // -> what about for coupling probably unusefull to be check
1990            storeIndex_fromSrv_.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1991         
1992          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1993
1994          listMsg.push_back(CMessage());
1995          listMsg.back() << serverGridId << isCompressible_ << listOutIndex.back();
1996
1997          event.push(*itRank, 1, listMsg.back());
1998        }
1999        client->sendEvent(event);
2000      }
2001      else
2002      {
2003         int indexSize = globalLocalIndexSendToServer.size();
2004         CArray<int,1> outLocalIndexToServer(indexSize);
2005         for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
2006         {
2007           outLocalIndexToServer(idx) = itIndex->second;
2008         }
2009
2010         const std::list<int>& ranks = client->getRanksServerNotLeader();
2011         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2012         {
2013           storeIndex_fromSrv_.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
2014         }
2015         client->sendEvent(event);
2016       }
2017    }
2018    else
2019    {
2020      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
2021      itGlobalMap = globalIndexOnServer_[receiverSize].begin();
2022      iteGlobalMap = globalIndexOnServer_[receiverSize].end();
2023
2024      std::map<int,std::vector<int> >localIndexTmp;
2025      std::map<int,std::vector<size_t> > globalIndexTmp;
2026      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
2027      {
2028        int serverRank = itGlobalMap->first;
2029        int indexSize = itGlobalMap->second.size();
2030        const std::vector<size_t>& indexVec = itGlobalMap->second;
2031        for (int idx = 0; idx < indexSize; ++idx)
2032        {
2033          itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
2034          if (iteIndex != itIndex)
2035          {
2036            globalIndexTmp[serverRank].push_back(itIndex->first);
2037            localIndexTmp[serverRank].push_back(itIndex->second);
2038          }
2039        }
2040      }
2041
2042      for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns)
2043      {
2044        rank = connectedServerRank_[receiverSize][ns];
2045        int nb = 0;
2046        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
2047          nb = globalIndexTmp[rank].size();
2048
2049        storeIndex_toSrv_[client].insert(make_pair(rank, CArray<int,1>(nb)));
2050        listOutIndex.push_back(CArray<size_t,1>(nb));
2051
2052        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv_[client][rank];
2053        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
2054
2055        for (int k = 0; k < nb; ++k)
2056        {
2057          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
2058          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
2059        }
2060
2061        storeIndex_fromSrv_.insert(make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
2062        listMsg.push_back(CMessage());
2063        listMsg.back() << serverGridId  << isCompressible_ << listOutIndex.back();
2064
2065        event.push(rank, nbSenders_[receiverSize][rank], listMsg.back());
2066      }
2067      client->sendEvent(event);
2068    }
2069  }
2070  CATCH_DUMP_ATTR
2071
2072  void CGrid::recvIndex(CEventServer& event)
2073  TRY
2074  {
2075    string gridId;
2076    vector<int> ranks;
2077    vector<CBufferIn*> buffers;
2078
2079    list<CEventServer::SSubEvent>::iterator it;
2080    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2081    {
2082      ranks.push_back(it->rank);
2083      CBufferIn* buffer = it->buffer;
2084      *buffer >> gridId;
2085      buffers.push_back(buffer);
2086    }
2087    get(gridId)->recvIndex(ranks, buffers, event.getContextServer());
2088  }
2089  CATCH
2090
2091  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers, CContextServer* server)
2092  TRY
2093  {
2094    CContextClient* client = server->getAssociatedClient();
2095    connectedServerRankRead_ = ranks;
2096    for (int n = 0; n < ranks.size(); n++)
2097    {
2098      int rank = ranks[n];
2099      CBufferIn& buffer = *buffers[n];
2100      buffer >>  isCompressible_; // probably to be removed later
2101      CArray<size_t,1> outIndex;
2102      buffer >> outIndex;
2103      outGlobalIndexFromClient_.insert(std::make_pair(rank, outIndex));
2104      connectedDataSizeRead_[rank] = outIndex.numElements();
2105    }
2106    // ym : displaced to avoid collective call at message reception
2107/*
2108    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize,
2109                                                                                     client->intraComm, ranks);
2110*/
2111  }
2112  CATCH_DUMP_ATTR
2113 
2114 
2115  /*!
2116   * Compute the number of connected client for a given contextClient and insert it in the nbReadSenders map.
2117   * /param[in] client : the given contextClient
2118   */
2119  void CGrid::computeNbReadSenders(CContextClient* client) 
2120  TRY
2121 
2122  { 
2123    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRankRead_);
2124  }
2125  CATCH_DUMP_ATTR
2126 
2127  void CGrid::computeServerDistribution(void)
2128  TRY
2129  {
2130    if (computeServerDistribution_done_) return ;
2131    else computeServerDistribution_done_=true ;
2132
2133    CContext* context = CContext::getCurrent();
2134     
2135    int idx = 0, numElement = axis_domain_order.numElements();
2136    int ssize = numElement;
2137    std::vector<int> indexMap(numElement);
2138    for (int i = 0; i < numElement; ++i)
2139    {
2140      indexMap[i] = idx;
2141      if (2 == axis_domain_order(i))
2142      {
2143        ++ssize;
2144        idx += 2;
2145      }
2146      else
2147        ++idx;
2148    }
2149
2150    for (int n = 0; n < connectedServerRankRead_.size(); n++)
2151    {
2152      int rank = connectedServerRankRead_[n];
2153      size_t dataSize = 0;
2154
2155      if (0 == serverDistribution_)
2156      {
2157        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
2158        std::vector<CDomain*> domainList = getDomains();
2159        std::vector<CAxis*> axisList = getAxis();
2160        std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement);
2161        std::vector<CArray<int,1> > globalIndex(numElement);
2162        for (int i = 0; i < numElement; ++i)
2163        {
2164          nGlobElement[i] = globalSize;
2165          if (2 == axis_domain_order(i)) //domain
2166          {
2167            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
2168            nSize[indexMap[i]]  = domainList[domainId]->ni;
2169            nBeginGlobal[indexMap[i]] = 0;
2170            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
2171
2172            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
2173            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
2174            nBeginGlobal[indexMap[i] + 1] = 0;
2175            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
2176
2177            {
2178              int count = 0;
2179              globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]);
2180              for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx)
2181                for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2182                {
2183                  globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
2184                  ++count;
2185                }
2186            }
2187
2188            ++domainId;
2189          }
2190          else if (1 == axis_domain_order(i)) // axis
2191          {
2192            nBegin[indexMap[i]] = axisList[axisId]->begin;
2193            nSize[indexMap[i]]  = axisList[axisId]->n;
2194            nBeginGlobal[indexMap[i]] = 0;
2195            nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
2196            globalIndex[i].resize(nSize[indexMap[i]]);
2197            for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2198              globalIndex[i](idx) = nBegin[indexMap[i]] + idx;
2199
2200            ++axisId;
2201          }
2202          else // scalar
2203          { 
2204            nBegin[indexMap[i]] = 0;
2205            nSize[indexMap[i]]  = 1;
2206            nBeginGlobal[indexMap[i]] = 0;
2207            nGlob[indexMap[i]] = 1;
2208            globalIndex[i].resize(1);
2209            globalIndex[i](0) = 0;
2210            ++scalarId;
2211          }
2212        }
2213        dataSize = 1;
2214
2215        for (int i = 0; i < nSize.size(); ++i)
2216        dataSize *= nSize[i];
2217        serverDistribution_ = new CDistributionServer(context->intraCommRank_, 
2218                                                      globalIndex, axis_domain_order,
2219                                                      nBegin, nSize, nBeginGlobal, nGlob);
2220      }
2221    }
2222  }
2223  CATCH_DUMP_ATTR
2224
2225
2226
2227
2228
2229
2230/* old interface => transform into compute receivedIndex
2231  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers, CContextServer* server)
2232  TRY
2233  {
2234    CContext* context = CContext::getCurrent();
2235    connectedServerRankRead_ = ranks;
2236
2237    nbReadSenders_.clear();
2238    CContextClient* client = server->getAssociatedClient();   
2239     
2240    int idx = 0, numElement = axis_domain_order.numElements();
2241    int ssize = numElement;
2242    std::vector<int> indexMap(numElement);
2243    for (int i = 0; i < numElement; ++i)
2244    {
2245      indexMap[i] = idx;
2246      if (2 == axis_domain_order(i))
2247      {
2248        ++ssize;
2249        idx += 2;
2250      }
2251      else
2252        ++idx;
2253    }
2254
2255    for (int n = 0; n < ranks.size(); n++)
2256    {
2257      int rank = ranks[n];
2258      CBufferIn& buffer = *buffers[n];
2259
2260      buffer >>  isCompressible_;
2261      size_t dataSize = 0;
2262
2263      if (0 == serverDistribution_)
2264      {
2265        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
2266        std::vector<CDomain*> domainList = getDomains();
2267        std::vector<CAxis*> axisList = getAxis();
2268        std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement);
2269        std::vector<CArray<int,1> > globalIndex(numElement);
2270        for (int i = 0; i < numElement; ++i)
2271        {
2272          nGlobElement[i] = globalSize;
2273          if (2 == axis_domain_order(i)) //domain
2274          {
2275            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
2276            nSize[indexMap[i]]  = domainList[domainId]->ni;
2277            nBeginGlobal[indexMap[i]] = 0;
2278            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
2279
2280            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
2281            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
2282            nBeginGlobal[indexMap[i] + 1] = 0;
2283            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
2284
2285            {
2286              int count = 0;
2287              globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]);
2288              for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx)
2289                for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2290                {
2291                  globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
2292                  ++count;
2293                }
2294            }
2295
2296            ++domainId;
2297          }
2298          else if (1 == axis_domain_order(i)) // axis
2299          {
2300            nBegin[indexMap[i]] = axisList[axisId]->begin;
2301            nSize[indexMap[i]]  = axisList[axisId]->n;
2302            nBeginGlobal[indexMap[i]] = 0;
2303            nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
2304            globalIndex[i].resize(nSize[indexMap[i]]);
2305            for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2306              globalIndex[i](idx) = nBegin[indexMap[i]] + idx;
2307
2308            ++axisId;
2309          }
2310          else // scalar
2311          {
2312            nBegin[indexMap[i]] = 0;
2313            nSize[indexMap[i]]  = 1;
2314            nBeginGlobal[indexMap[i]] = 0;
2315            nGlob[indexMap[i]] = 1;
2316            globalIndex[i].resize(1);
2317            globalIndex[i](0) = 0;
2318            ++scalarId;
2319          }
2320        }
2321        dataSize = 1;
2322
2323        for (int i = 0; i < nSize.size(); ++i)
2324        dataSize *= nSize[i];
2325        serverDistribution_ = new CDistributionServer(context->intraCommRank_,
2326                                                      globalIndex, axis_domain_order,
2327                                                      nBegin, nSize, nBeginGlobal, nGlob);
2328      }
2329
2330      CArray<size_t,1> outIndex;
2331      buffer >> outIndex;
2332      outGlobalIndexFromClient_.insert(std::make_pair(rank, outIndex));
2333      connectedDataSizeRead_[rank] = outIndex.numElements();
2334
2335      if (doGridHaveDataDistributed(client))
2336      {}
2337      else
2338      {
2339        // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
2340        // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
2341        dataSize = serverDistribution_->getGridSize();
2342      }
2343      writtenDataSize_ += dataSize;
2344    }
2345
2346
2347    // Compute mask of the current grid
2348    {
2349      int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
2350      std::vector<CDomain*> domainList = getDomains();
2351      std::vector<CAxis*> axisList = getAxis();
2352      int dimSize = 2 * domainList.size() + axisList.size();
2353      std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize);       
2354      for (int i = 0; i < numElement; ++i)
2355      {         
2356        if (2 == axis_domain_order(i)) //domain
2357        {
2358          nBegin[indexMap[i]] = domainList[domainId]->ibegin;
2359          nSize[indexMap[i]]  = domainList[domainId]->ni;
2360          nBeginGlobal[indexMap[i]] = 0;             
2361          nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
2362
2363          nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
2364          nSize[indexMap[i] + 1] = domainList[domainId]->nj;
2365          nBeginGlobal[indexMap[i] + 1] = 0;             
2366          nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
2367          ++domainId;
2368        }
2369        else if (1 == axis_domain_order(i)) // axis
2370        {
2371          nBegin[indexMap[i]] = axisList[axisId]->begin;
2372          nSize[indexMap[i]]  = axisList[axisId]->n;
2373          nBeginGlobal[indexMap[i]] = 0;             
2374          nGlob[indexMap[i]] = axisList[axisId]->n_glo;             
2375          ++axisId;
2376        }
2377        else // scalar
2378        { 
2379        }
2380      }
2381     
2382      if (nSize.empty()) // Scalar grid
2383      {
2384        nBegin.push_back(0);
2385        nSize.push_back(1);
2386        nBeginGlobal.push_back(0);             
2387        nGlob.push_back(1); 
2388      }
2389    }
2390
2391    if (isScalarGrid()) return;
2392
2393    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize,
2394                                                                                      client->intraComm, ranks);
2395
2396  }
2397  CATCH_DUMP_ATTR
2398*/
2399
2400
2401  /*
2402     Compute on the fly the global dimension of a grid with its elements
2403     \param[in/out] globalDim global dimension of grid
2404     \param[in] domains list of its domains
2405     \param[in] axiss list of its axis
2406     \param[in] scalars list of its scalars
2407     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
2408     \return The dimension of which we do distribution (often for server)
2409  */
2410  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
2411                                        const std::vector<CDomain*> domains,
2412                                        const std::vector<CAxis*> axis,
2413                                        const std::vector<CScalar*> scalars,
2414                                        const CArray<int,1>& axisDomainOrder)
2415  TRY
2416 {
2417 //   globalDim.resize(domains.size()*2+axis.size()+scalars.size());
2418    globalDim.resize(domains.size()*2+axis.size());
2419    int positionDimensionDistributed = 1;
2420    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
2421    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
2422    {
2423      if (2 == axisDomainOrder(i))
2424      {
2425        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
2426        {
2427          positionDimensionDistributed = idx;
2428        }
2429        else
2430        {
2431          positionDimensionDistributed = idx +1;
2432        }
2433
2434        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
2435        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
2436
2437        ++idxDomain;
2438        idx += 2;
2439      }
2440      else if (1 == axisDomainOrder(i))
2441      {
2442        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
2443        ++idxAxis;
2444        ++idx;
2445      }
2446      else
2447      {
2448//        globalDim[idx] = 1;
2449        ++idxScalar;
2450//        ++idx;
2451      }
2452    }
2453
2454    return positionDimensionDistributed;
2455  }
2456  CATCH_DUMP_ATTR
2457
2458  // Retrieve the global dimension of grid
2459  std::vector<int> CGrid::getGlobalDimension()
2460  TRY
2461  {
2462    std::vector<int> globalDim;
2463    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
2464
2465    return globalDim;
2466  }
2467  CATCH_DUMP_ATTR
2468
2469  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
2470  int CGrid::getDistributedDimension()
2471  TRY
2472  {
2473    std::vector<int> globalDim;
2474    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
2475  }
2476  CATCH_DUMP_ATTR
2477
2478  bool CGrid::isScalarGrid() const
2479  TRY
2480  {
2481    return (axisList_.empty() && domList_.empty());
2482  }
2483  CATCH
2484
2485  /*!
2486    Verify whether one server need to write data
2487    There are some cases on which one server has nodata to write. For example, when we
2488    just only want to zoom on a domain.
2489  */
2490  bool CGrid::doGridHaveDataToWrite()
2491  TRY
2492  {
2493     return (0 != getGridLocalElements()->getView(CElementView::FULL)->getSize());
2494  }
2495  CATCH_DUMP_ATTR
2496
2497  /*!
2498    Return size of data which is written on each server
2499    Whatever dimension of a grid, data which are written on server must be presented as
2500    an one dimension array.
2501    \return size of data written on server
2502  */
2503  size_t CGrid::getWrittenDataSize() 
2504  TRY
2505  {
2506    return getGridLocalElements()->getView(CElementView::FULL)->getSize() ;
2507  }
2508  CATCH
2509
2510  /*!
2511    Returns the number of indexes written by each server.
2512    \return the number of indexes written by each server
2513  */
2514  int CGrid::getNumberWrittenIndexes() const
2515  TRY
2516  {
2517    return numberWrittenIndexes_;
2518  }
2519  CATCH
2520
2521  /*!
2522    Returns the total number of indexes written by the servers.
2523    \return the total number of indexes written by the servers
2524  */
2525  int CGrid::getTotalNumberWrittenIndexes() const
2526  TRY
2527  {
2528    return totalNumberWrittenIndexes_;
2529  }
2530  CATCH
2531
2532  /*!
2533    Returns the offset of indexes written by each server.
2534    \return the offset of indexes written by each server
2535  */
2536  int CGrid::getOffsetWrittenIndexes() const
2537  TRY
2538  {
2539    return offsetWrittenIndexes_;
2540  }
2541  CATCH
2542
2543 
2544  CDistributionClient* CGrid::getClientDistribution()
2545  TRY
2546  {
2547    if (!computeClientDistribution_done_) computeClientDistribution() ;
2548    return clientDistribution_;
2549  }
2550  CATCH_DUMP_ATTR
2551
2552  bool CGrid::doGridHaveDataDistributed(CContextClient* client)
2553  TRY
2554  {
2555    // This function is now useless because it will return false only if server and client size are equal to 1
2556    // to be seriously check in future
2557
2558    if (isScalarGrid()) return false;
2559    else if (0 != client)
2560    {
2561      return  (isDataDistributed() ||  (1 != client->clientSize) || (1 != client->serverSize));
2562    }
2563    else
2564      return isDataDistributed();   
2565  }
2566  CATCH_DUMP_ATTR
2567
2568   /*!
2569   \brief Dispatch event received from client
2570      Whenever a message is received in buffer of server, it will be processed depending on
2571   its event type. A new event type should be added in the switch list to make sure
2572   it processed on server side.
2573   \param [in] event: Received message
2574   */
2575  bool CGrid::dispatchEvent(CEventServer& event)
2576  TRY
2577  {
2578
2579    if (SuperClass::dispatchEvent(event)) return true;
2580    else
2581    {
2582      switch(event.type)
2583      {
2584        case EVENT_ID_INDEX :
2585          recvIndex(event);
2586          return true;
2587          break;
2588
2589         case EVENT_ID_ADD_DOMAIN :
2590           recvAddDomain(event);
2591           return true;
2592           break;
2593
2594         case EVENT_ID_ADD_AXIS :
2595           recvAddAxis(event);
2596           return true;
2597           break;
2598
2599         case EVENT_ID_ADD_SCALAR :
2600           recvAddScalar(event);
2601           return true;
2602           break;
2603
2604         case EVENT_ID_SEND_MASK :
2605           recvMask(event);
2606           return true;
2607           break;
2608        default :
2609          ERROR("bool CGrid::dispatchEvent(CEventServer& event)",
2610                << "Unknown Event");
2611          return false;
2612      }
2613    }
2614  }
2615  CATCH
2616
2617 
2618
2619  void CGrid::sendGridToFileServer(CContextClient* client)
2620  {
2621    if (sendGridToFileServer_done_.count(client)!=0) return ;
2622    else sendGridToFileServer_done_.insert(client) ;
2623
2624    StdString gridDefRoot("grid_definition");
2625    CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
2626    gridPtr->sendCreateChild(this->getId(),client);
2627    this->sendAllAttributesToServer(client);
2628    //if (isScalarGrid())  sendIndexScalarGrid(client);
2629    //else  sendIndex(client);
2630    //this->sendAllDomains(client);
2631    //this->sendAllAxis(client);
2632    //this->sendAllScalars(client);
2633
2634    distributeGridToFileServer(client) ;
2635  }
2636
2637
2638  void CGrid::distributeGridToFileServer(CContextClient* client)
2639  {
2640    CContext* context = CContext::getCurrent();
2641    // simple Distribution for now
2642    // distribute over the fisrt element except if it is a scalar
2643    auto& elements = getElements() ;
2644    int posDistributed = 0 ;
2645    for(auto& element : elements)
2646    {
2647      if (element.type==TYPE_DOMAIN) break ;
2648      else if (element.type==TYPE_AXIS) break ;
2649      else if (element.type==TYPE_SCALAR) posDistributed++ ;
2650    }
2651   
2652    vector<CLocalView*> localViews ;
2653    vector<CDistributedView*> remoteViews ;
2654
2655    for(int i=0 ; i<elements.size() ; i++)
2656    {
2657      if (elements[i].type==TYPE_DOMAIN) 
2658      { 
2659         CDomain* domain = (CDomain*) elements[i].ptr ;
2660         domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2661         remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ;
2662         localViews.push_back(domain->getLocalView(CElementView::FULL)) ;
2663      }
2664      else if (elements[i].type==TYPE_AXIS)
2665      {
2666        CAxis* axis = (CAxis*) elements[i].ptr ;
2667        axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2668        remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ;
2669        localViews.push_back(axis->getLocalView(CElementView::FULL)) ;
2670      }
2671      else if (elements[i].type==TYPE_SCALAR)
2672      {
2673        CScalar* scalar = (CScalar*) elements[i].ptr ;
2674        scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2675        remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ;
2676        localViews.push_back(scalar->getLocalView(CElementView::FULL)) ;
2677      }
2678    }
2679    CGridRemoteConnector gridRemoteConnector(localViews, remoteViews, context->getIntraComm(), client->getRemoteSize()) ;
2680    gridRemoteConnector.computeConnector() ;
2681   
2682    vector<CScattererConnector*> scattererConnectors ;
2683    for(int i=0 ; i<elements.size() ; i++)
2684    {
2685      if (elements[i].type==TYPE_DOMAIN) 
2686      { 
2687         CDomain* domain = (CDomain*) elements[i].ptr ;
2688         sendAddDomain(domain->getId(),client) ;
2689         domain->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2690         scattererConnectors.push_back(domain->getClientToServerConnector(client)) ;
2691      }
2692      else if (elements[i].type==TYPE_AXIS)
2693      {
2694        CAxis* axis = (CAxis*) elements[i].ptr ;
2695        sendAddAxis(axis->getId(),client) ;
2696        axis->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2697        scattererConnectors.push_back(axis->getClientToServerConnector(client)) ;
2698      }
2699      else if (elements[i].type==TYPE_SCALAR)
2700      {
2701        CScalar* scalar = (CScalar*) elements[i].ptr ;
2702        sendAddScalar(scalar->getId(),client) ;
2703        scalar->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2704        scattererConnectors.push_back(scalar->getClientToServerConnector(client)) ;
2705      }
2706    }
2707
2708    CGridScattererConnector gridScattererConnector(scattererConnectors) ;
2709    CGridLocalConnector* workflowToFull = getGridLocalElements()->getConnector(CElementView::WORKFLOW, CElementView::FULL) ;
2710    CArray<bool,1> maskIn(workflowToFull->getSrcSize()) ;
2711    CArray<bool,1> maskOut(workflowToFull->getDstSize()) ;
2712    maskIn = true ;
2713    workflowToFull->transfer(maskIn,maskOut,false) ;
2714
2715    CEventClient event(getType(), EVENT_ID_SEND_MASK);
2716    CMessage message ;
2717    message<<getId() ; 
2718    gridScattererConnector.transfer(maskOut, client, event, message) ;
2719
2720
2721    vector<CScattererConnector*> clientToServerConnectors ;
2722    vector<CGathererConnector*>  clientFromServerConnectors ;
2723    for(auto& element : elements)
2724    {
2725      if (element.type==TYPE_DOMAIN) 
2726      { 
2727         clientToServerConnectors.push_back(element.domain->getClientToServerConnector(client)) ;
2728         clientFromServerConnectors.push_back(element.domain->getClientFromServerConnector(client)) ;
2729      }
2730      else if (element.type==TYPE_AXIS)
2731      {
2732        clientToServerConnectors.push_back(element.axis->getClientToServerConnector(client)) ;
2733        clientFromServerConnectors.push_back(element.axis->getClientFromServerConnector(client)) ;
2734
2735      }
2736      else if (element.type==TYPE_SCALAR)
2737      {
2738        clientToServerConnectors.push_back(element.scalar->getClientToServerConnector(client)) ;
2739        clientFromServerConnectors.push_back(element.scalar->getClientFromServerConnector(client)) ;
2740      }
2741    }
2742   
2743    // compute the grid clientToServerConnector to send flux from client to servers
2744    clientToServerConnector_[client] = new CGridScattererConnector(clientToServerConnectors) ;
2745    clientFromServerConnector_[client] = new CGridGathererConnector(clientFromServerConnectors) ;
2746
2747
2748  }
2749
2750  void CGrid::recvMask(CEventServer& event)
2751  {
2752    string gridId;
2753    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> gridId  ;
2754    get(gridId)->receiveMask(event);
2755  }
2756 
2757  void CGrid::receiveMask(CEventServer& event)
2758  {
2759    vector<CGathererConnector*> gathererConnectors ;
2760    vector<CLocalView*> fullViews ;
2761
2762    for(auto& element : getElements())
2763    {
2764      if (element.type==TYPE_DOMAIN) 
2765      {
2766        gathererConnectors.push_back(element.domain->getGathererConnector());
2767        fullViews.push_back(element.domain->getLocalElement()->getView(CElementView::FULL));
2768       
2769      }
2770      else if (element.type==TYPE_AXIS)
2771      {
2772       gathererConnectors.push_back(element.axis->getGathererConnector());
2773       fullViews.push_back(element.axis->getLocalElement()->getView(CElementView::FULL));
2774      }
2775      else if (element.type==TYPE_SCALAR) 
2776      {
2777        gathererConnectors.push_back(element.scalar->getGathererConnector());
2778        fullViews.push_back(element.scalar->getLocalElement()->getView(CElementView::FULL));
2779      }
2780    }
2781    CGridGathererConnector gridGathererConnector(gathererConnectors) ;
2782    CGridMaskConnector gridMaskConnector(fullViews) ;
2783
2784    CArray<bool,1> maskOut ;
2785    gridGathererConnector.transfer(event,maskOut,false) ;
2786    gridMaskConnector.computeConnector(maskOut) ;
2787
2788    CContextClient* client = event.getContextServer()->getAssociatedClient() ;
2789    int i=0 ;
2790    for(auto& element : getElements())
2791    {
2792      if (element.type==TYPE_DOMAIN) element.domain->setServerMask(gridMaskConnector.getElementMask(i),client);
2793      else if (element.type==TYPE_AXIS) element.axis->setServerMask(gridMaskConnector.getElementMask(i),client);
2794      else if (element.type==TYPE_SCALAR) element.scalar->setServerMask(gridMaskConnector.getElementMask(i),client);
2795      i++ ;
2796    }
2797  }
2798
2799
2800  void CGrid::sendGridToCouplerOut(CContextClient* client, const string& fieldId)
2801  {
2802    if (sendGridToCouplerOut_done_.count(client)!=0) return ;
2803    else sendGridToCouplerOut_done_.insert(client) ;
2804 
2805    CContext* context = CContext::getCurrent();
2806    // simple Distribution for now
2807    // distribute over the fisrt element except if it is a scalar
2808    auto& elements = getElements() ;
2809    int posDistributed = 0 ;
2810    for(auto& element : elements)
2811    {
2812      if (element.type==TYPE_DOMAIN) break ;
2813      else if (element.type==TYPE_AXIS) break ;
2814      else if (element.type==TYPE_SCALAR) posDistributed++ ;
2815    }
2816   
2817    vector<CLocalView*> localViews ;
2818    vector<CDistributedView*> remoteViews ;
2819
2820    for(int i=0 ; i<elements.size() ; i++)
2821    {
2822      if (elements[i].type==TYPE_DOMAIN) 
2823      { 
2824         CDomain* domain = (CDomain*) elements[i].ptr ;
2825         domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2826         remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ;
2827         localViews.push_back(domain->getLocalView(CElementView::FULL)) ;
2828      }
2829      else if (elements[i].type==TYPE_AXIS)
2830      {
2831        CAxis* axis = (CAxis*) elements[i].ptr ;
2832        axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2833        remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ;
2834        localViews.push_back(axis->getLocalView(CElementView::FULL)) ;
2835      }
2836      else if (elements[i].type==TYPE_SCALAR)
2837      {
2838        CScalar* scalar = (CScalar*) elements[i].ptr ;
2839        scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2840        remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ;
2841        localViews.push_back(scalar->getLocalView(CElementView::FULL)) ;
2842      }
2843    }
2844    CGridRemoteConnector gridRemoteConnector(localViews, remoteViews, context->getIntraComm(), client->getRemoteSize()) ;
2845    gridRemoteConnector.computeConnector() ;
2846   
2847    vector<CScattererConnector*> clientToClientConnectors ;
2848    for(int i=0 ; i<elements.size() ; i++)
2849    {
2850      if (elements[i].type==TYPE_DOMAIN) 
2851      { 
2852         CDomain* domain = (CDomain*) elements[i].ptr ;
2853         sendAddDomain(domain->getId(),client) ;
2854         domain->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2855         clientToClientConnectors.push_back(domain->getClientToServerConnector(client)) ;
2856      }
2857      else if (elements[i].type==TYPE_AXIS)
2858      {
2859        CAxis* axis = (CAxis*) elements[i].ptr ;
2860        sendAddAxis(axis->getId(),client) ;
2861        axis->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2862        clientToClientConnectors.push_back(axis->getClientToServerConnector(client)) ;
2863      }
2864      else if (elements[i].type==TYPE_SCALAR)
2865      {
2866        CScalar* scalar = (CScalar*) elements[i].ptr ;
2867        sendAddScalar(scalar->getId(),client) ;
2868        scalar->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2869        clientToClientConnectors.push_back(scalar->getClientToServerConnector(client)) ;
2870      }
2871    }
2872   
2873    // compute the grid clientToServerConnector to send flux from client to servers
2874    clientToClientConnector_[client] = new CGridScattererConnector(clientToClientConnectors) ;
2875  }
2876
2877  void CGrid::makeAliasForCoupling(const string& fieldId)
2878  {
2879    string gridId="_grid_of_"+fieldId ;
2880    createAlias(gridId) ;
2881   
2882    const auto& domVect = getDomains() ;
2883    for (int pos=0; pos<domVect.size();pos++) domVect[pos]->makeAliasForCoupling(fieldId, pos);
2884
2885    const auto& axisVect=getAxis() ;
2886    for (int pos=0; pos<axisVect.size();pos++) axisVect[pos]->makeAliasForCoupling(fieldId, pos);
2887
2888    const auto& scalVect=getScalars() ;
2889    for (int pos=0; pos<scalVect.size();pos++) scalVect[pos]->makeAliasForCoupling(fieldId, pos);
2890  }
2891
2892   /*!
2893   \brief Send a message to create a domain on server side
2894   \param[in] id String identity of domain that will be created on server
2895   */
2896   void CGrid::sendAddDomain(const string& id, CContextClient* contextClient)
2897   TRY
2898  {
2899      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN, contextClient);
2900   }
2901   CATCH_DUMP_ATTR
2902
2903   /*!
2904   \brief Send a message to create an axis on server side
2905   \param[in] id String identity of axis that will be created on server
2906   */
2907   void CGrid::sendAddAxis(const string& id, CContextClient* contextClient)
2908   TRY
2909   {
2910      sendAddItem(id, (int)EVENT_ID_ADD_AXIS, contextClient);
2911   }
2912   CATCH_DUMP_ATTR
2913
2914   /*!
2915   \brief Send a message to create a scalar on server side
2916   \param[in] id String identity of scalar that will be created on server
2917   */
2918   void CGrid::sendAddScalar(const string& id, CContextClient* contextClient)
2919   TRY
2920   {
2921      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR, contextClient);
2922   }
2923   CATCH_DUMP_ATTR
2924
2925   /*!
2926   \brief Receive a message annoucing the creation of a domain on server side
2927   \param[in] event Received event
2928   */
2929   void CGrid::recvAddDomain(CEventServer& event)
2930   TRY
2931   {
2932
2933      CBufferIn* buffer = event.subEvents.begin()->buffer;
2934      string id;
2935      *buffer >> id;
2936      get(id)->recvAddDomain(*buffer);
2937   }
2938   CATCH
2939
2940   /*!
2941   \brief Receive a message annoucing the creation of a domain on server side
2942   \param[in] buffer Buffer containing message
2943   */
2944   void CGrid::recvAddDomain(CBufferIn& buffer)
2945   TRY
2946   {
2947      string id;
2948      buffer >> id;
2949      addDomain(id);
2950   }
2951   CATCH_DUMP_ATTR
2952
2953   /*!
2954   \brief Receive a message annoucing the creation of an axis on server side
2955   \param[in] event Received event
2956   */
2957   void CGrid::recvAddAxis(CEventServer& event)
2958   TRY
2959   {
2960
2961      CBufferIn* buffer = event.subEvents.begin()->buffer;
2962      string id;
2963      *buffer >> id;
2964      get(id)->recvAddAxis(*buffer);
2965   }
2966   CATCH
2967
2968   /*!
2969   \brief Receive a message annoucing the creation of an axis on server side
2970   \param[in] buffer Buffer containing message
2971   */
2972   void CGrid::recvAddAxis(CBufferIn& buffer)
2973   TRY
2974   {
2975      string id;
2976      buffer >> id;
2977      addAxis(id);
2978   }
2979   CATCH_DUMP_ATTR
2980
2981   /*!
2982   \brief Receive a message annoucing the creation of an scalar on server side
2983   \param[in] event Received event
2984   */
2985   void CGrid::recvAddScalar(CEventServer& event)
2986   TRY
2987   {
2988
2989      CBufferIn* buffer = event.subEvents.begin()->buffer;
2990      string id;
2991      *buffer >> id;
2992      get(id)->recvAddScalar(*buffer);
2993   }
2994   CATCH
2995
2996   /*!
2997   \brief Receive a message annoucing the creation of an scalar on server side
2998   \param[in] buffer Buffer containing message
2999   */
3000   void CGrid::recvAddScalar(CBufferIn& buffer)
3001   TRY
3002   {
3003      string id;
3004      buffer >> id;
3005      addScalar(id);
3006   }
3007   CATCH_DUMP_ATTR
3008
3009  /*!
3010  \brief Check if all elements of the grid are complete
3011  Before make any grid processing, we must be sure that all grid information elements have
3012  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
3013  other context (coupling)
3014  */
3015  bool CGrid::isCompleted(void)
3016  {
3017    setDomainList();
3018    for (auto domainId : domList_) if (!CDomain::get(domainId)->isCompleted()) return false ;
3019    setAxisList() ;
3020    for (auto axisId : axisList_) if (!CAxis::get(axisId)->isCompleted()) return false ;
3021    setScalarList() ;
3022    for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->isCompleted()) return false ;
3023    return true ;
3024  }
3025
3026  /*!
3027  \brief impose that all elements of the grid are complete
3028  Before make any grid processing, we must be sure that all grid information elements have
3029  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
3030  other context (coupling)
3031  */
3032  void CGrid::setCompleted(void)
3033  {
3034    setDomainList();
3035    for (auto domainId : domList_) CDomain::get(domainId)->setCompleted() ;
3036    setAxisList() ;
3037    for (auto axisId : axisList_) CAxis::get(axisId)->setCompleted() ;
3038    setScalarList() ;
3039    for (auto scalarId : scalarList_) CScalar::get(scalarId)->setCompleted() ;
3040  }
3041
3042/*!
3043  \brief impose that all elements of the grid are incomplete
3044  Before make any grid processing, we must be sure that all grid information elements have
3045  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
3046  other context (coupling)
3047  */
3048  void CGrid::unsetCompleted(void)
3049  {
3050    setDomainList();
3051    for (auto domainId : domList_) CDomain::get(domainId)->unsetCompleted() ;
3052    setAxisList() ;
3053    for (auto axisId : axisList_) CAxis::get(axisId)->unsetCompleted() ;
3054    setScalarList() ;
3055    for (auto scalarId : scalarList_) CScalar::get(scalarId)->unsetCompleted() ;
3056  }
3057
3058  /*!
3059  \brief Solve domain and axis references
3060  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
3061  all attributes from their parents, they should be processed with this function
3062  \param[in] apply inherit all attributes of parents (true)
3063  */
3064  void CGrid::solveElementsRefInheritance(bool apply)
3065  TRY
3066  {
3067    setDomainList();
3068    for (auto domainId : domList_)
3069    {
3070      CDomain* pDom = CDomain::get(domainId);
3071      pDom->solveRefInheritance(apply);
3072      pDom->solveInheritanceTransformation();
3073    }
3074
3075    setAxisList();
3076    for (auto axisId : axisList_)
3077    {
3078      CAxis* pAxis = CAxis::get(axisId);
3079      pAxis->solveRefInheritance(apply);
3080      pAxis->solveInheritanceTransformation();
3081    }
3082
3083    setScalarList();
3084    for (auto scalarId : scalarList_)
3085    {
3086      CScalar* pScalar = CScalar::get(scalarId);
3087      pScalar->solveRefInheritance(apply);
3088      pScalar->solveInheritanceTransformation();
3089    }
3090  }
3091  CATCH_DUMP_ATTR
3092
3093 /*!
3094  \brief check attributes of all elements of the grid
3095  */
3096  void CGrid::checkElementsAttributes(void)
3097  TRY
3098  {
3099    setDomainList();
3100    for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes();
3101
3102    setAxisList();
3103    for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes();
3104   
3105    setScalarList();
3106    for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes();
3107  }
3108  CATCH_DUMP_ATTR
3109
3110  bool CGrid::isTransformed()
3111  TRY
3112  {
3113    return isTransformed_;
3114  }
3115  CATCH_DUMP_ATTR
3116
3117  void CGrid::setTransformed()
3118  TRY
3119  {
3120    isTransformed_ = true;
3121  }
3122  CATCH_DUMP_ATTR
3123
3124  CGridTransformation* CGrid::getTransformations()
3125  TRY
3126  {
3127    return transformations_;
3128  }
3129  CATCH_DUMP_ATTR
3130
3131  void CGrid::addTransGridSource(CGrid* gridSrc)
3132  TRY
3133  {
3134    if (gridSrc_.end() == gridSrc_.find(gridSrc))
3135      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
3136  }
3137  CATCH_DUMP_ATTR
3138
3139  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
3140  TRY
3141  {
3142    return gridSrc_;
3143  }
3144  CATCH_DUMP_ATTR
3145
3146  /*!
3147     Complete all the necessary (and lacking) attributes of a grid
3148     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
3149  */
3150  void CGrid::completeGrid(CGrid* transformGridSrc)
3151  TRY
3152  {
3153    if (nullptr != transformGridSrc)
3154    {
3155      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
3156      {
3157        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
3158             << "Two grids have different number of elements. " << std::endl
3159             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
3160             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
3161      }
3162    }
3163
3164    if (isGenerated()) return;
3165    setGenerated();
3166
3167    CGridGenerate gridGenerate(this, transformGridSrc);
3168    gridGenerate.completeGrid();
3169  }
3170  CATCH_DUMP_ATTR
3171
3172  bool CGrid::isGenerated()
3173  TRY
3174  {
3175    return isGenerated_;
3176  }
3177  CATCH
3178
3179  void CGrid::setGenerated()
3180  TRY
3181  {
3182    isGenerated_ = true;
3183  }
3184  CATCH_DUMP_ATTR
3185
3186  void CGrid::transformGrid(CGrid* transformGridSrc)
3187  TRY
3188  {
3189    if (!transformGridSrc)
3190      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3191            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
3192
3193    if (isTransformed()) return;
3194    setTransformed();
3195    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
3196    {
3197      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3198           << "Two grids have different number of elements. " << std::endl
3199           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
3200           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
3201    }
3202    else
3203    {
3204    }
3205
3206    transformations_ = new CGridTransformation(this, transformGridSrc);
3207    transformations_->computeAll();
3208    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
3209
3210    // Ok, now need to compute index of grid source
3211    transformGridSrc->checkMaskIndex(false);
3212  }
3213  CATCH_DUMP_ATTR
3214
3215
3216
3217
3218  void CGrid::prepareTransformGrid(CGrid* transformGridSrc)
3219  TRY
3220  {
3221    if (prepareTransformGrid_done_) return ;
3222
3223    if (!transformGridSrc)
3224      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3225            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
3226
3227    if (isTransformed()) return;
3228    setTransformed();
3229    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
3230    {
3231      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3232           << "Two grids have different number of elements. " << std::endl
3233           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
3234           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
3235    }
3236    else
3237    {
3238    }
3239
3240    transformations_ = new CGridTransformation(this, transformGridSrc);
3241    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
3242
3243    prepareTransformGrid_done_ = true; 
3244  }
3245  CATCH_DUMP_ATTR
3246
3247
3248  void CGrid::makeTransformGrid(void)
3249  TRY
3250  {
3251    if (makeTransformGrid_done_) return ;
3252    transformations_->computeAll();
3253
3254    makeTransformGrid_done_ = true ; 
3255  }
3256  CATCH_DUMP_ATTR
3257
3258
3259  vector<std::string> CGrid::getAuxInputTransformGrid(void)
3260  TRY
3261  {
3262    if (transformations_ != nullptr) return transformations_->getAuxInputs() ;
3263  }
3264  CATCH_DUMP_ATTR
3265
3266
3267
3268
3269
3270
3271
3272  bool CGrid::hasTransform()
3273  TRY
3274  {
3275    if (hasTransform_) return hasTransform_;
3276
3277    std::vector<CDomain*> domList = getDomains();
3278    std::vector<CAxis*> axisList = getAxis();
3279    std::vector<CScalar*> scalarList = getScalars();
3280
3281    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
3282    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
3283    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
3284
3285    return hasTransform_;
3286  }
3287  CATCH_DUMP_ATTR
3288
3289
3290
3291  /*!
3292    Send all attributes of domains from client to server
3293  */
3294  void CGrid::sendAllDomains(CContextClient* contextClient)
3295  TRY
3296  {
3297    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
3298    for (auto domain : domList)
3299    {
3300      sendAddDomain(domain->getId(),contextClient);
3301      domain->sendDomainToFileServer(contextClient);
3302    }
3303  }
3304  CATCH_DUMP_ATTR
3305
3306  /*!
3307    Send all attributes of axis from client to server
3308  */
3309  void CGrid::sendAllAxis(CContextClient* contextClient)
3310  TRY
3311  {
3312    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
3313    for (int i=0; i<aList.size() ; ++i)
3314    {
3315      sendAddAxis(aList[i]->getId(),contextClient);
3316      aList[i]->sendAxisToFileServer(contextClient, getGlobalDimension(), getAxisPositionInGrid()[i]);
3317    }
3318  }
3319  CATCH_DUMP_ATTR
3320
3321  /*!
3322    Send all attributes of scalars from client to server
3323  */
3324  void CGrid::sendAllScalars(CContextClient* contextClient)
3325  TRY
3326  {
3327    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
3328    for (auto scalar : sList)
3329    {
3330      sendAddScalar(scalar->getId(),contextClient);
3331      scalar->sendScalarToFileServer(contextClient);
3332    }
3333  }
3334  CATCH_DUMP_ATTR
3335
3336  void CGrid::setContextClient(CContextClient* contextClient)
3337  TRY
3338  {
3339    if (clientsSet.find(contextClient)==clientsSet.end())
3340    {
3341      clients.push_back(contextClient) ;
3342      clientsSet.insert(contextClient);
3343    }
3344    for (auto domain : getDomains()) domain->setContextClient(contextClient);
3345    for (auto axis : getAxis()) axis->setContextClient(contextClient);
3346    for (auto scalar : getScalars()) scalar->setContextClient(contextClient);
3347   
3348  }
3349  CATCH_DUMP_ATTR
3350
3351 
3352  void CGrid::computeGridLocalElements()
3353  {
3354    std::vector<CDomain*> domainList = this->getDomains();
3355    std::vector<CAxis*> axisList = this->getAxis();
3356    std::vector<CScalar*> scalarList = this->getScalars();
3357    auto domain=domainList.begin() ;
3358    auto axis=axisList.begin() ;
3359    auto scalar=scalarList.begin() ;
3360    vector<CLocalElement*> elements;
3361    for(auto order : order_)
3362    {
3363      if (order==2) 
3364      {
3365        elements.push_back((*domain)->getLocalElement());
3366        domain++ ;
3367      }
3368      else if (order==1)
3369      {
3370        elements.push_back((*axis)->getLocalElement());
3371        axis++ ;
3372      }
3373      else if (order==0)
3374      { 
3375        elements.push_back((*scalar)->getLocalElement());
3376        scalar++ ;
3377      }
3378    }
3379    if (hasMask()) 
3380    {
3381      vector<bool> mask(getMask().getVector()) ;
3382      gridLocalElements_ = new CGridLocalElements(elements, mask) ; 
3383    }
3384    else gridLocalElements_ = new CGridLocalElements(elements) ; 
3385  }
3386
3387  void CGrid::computeModelToWorkflowConnector(void)
3388  {
3389    modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW) ;
3390  }
3391
3392  void CGrid::computeWorkflowToFullConnector(void)
3393  {
3394    workflowToFullConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::FULL) ;
3395  }
3396
3397  void CGrid::computeWorkflowToModelConnector(void)
3398  {
3399    workflowToModelConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::MODEL) ;
3400  }
3401
3402  void CGrid::computeFullToWorkflowConnector(void)
3403  {
3404    fullToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::FULL,CElementView::WORKFLOW) ;
3405  }
3406
3407  void CGrid::computeServerFromClientConnector(void)
3408  {
3409    vector<CGathererConnector*> connectors ;
3410    for(auto& element : getElements())
3411    {
3412      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
3413      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
3414      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
3415    }
3416    serverFromClientConnector_ = new CGridGathererConnector(connectors) ;
3417  }
3418
3419  void CGrid::computeServerToClientConnector(void)
3420  {
3421    vector<CScattererConnector*> connectors ;
3422    for(auto& element : getElements())
3423    {
3424      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerToClientConnector()) ;
3425      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerToClientConnector()) ; 
3426      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerToClientConnector()) ; 
3427    }
3428    serverToClientConnector_ = new CGridScattererConnector(connectors) ;
3429  }
3430
3431  void CGrid::computeClientFromClientConnector(void)
3432  {
3433    vector<CGathererConnector*> connectors ;
3434    for(auto& element : getElements())
3435    {
3436      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
3437      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
3438      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
3439    }
3440    clientFromClientConnector_ = new CGridGathererConnector(connectors) ;
3441  }
3442
3443 
3444} // namespace xios
Note: See TracBrowser for help on using the repository browser.