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

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

Xios coupling branch

  • Update connectors mechanism for scalar, similarly for domain and axis
  • add mask attribute to scalar

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