source: XIOS3/branches/xios-3.0-beta/src/node/grid.cpp @ 2423

Last change on this file since 2423 was 2397, checked in by ymipsl, 22 months ago
  • Optimize remote connector computation in case of read (reverse way).
  • don't compute anymore clientFromServerConnector (and all intermediate computation) for non reading case.

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: 84.5 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 "server.hpp"
19#include "distribution_type.hpp"
20#include "grid_client_server_remote_connector.hpp"
21#include "grid_elements.hpp"
22#include "grid_local_view.hpp"
23#include "grid_mask_connector.hpp"
24#include "transformation_path.hpp"
25#include "grid_transformation_factory_impl.hpp"
26#include "transform_filter.hpp"
27#include "grid_algorithm.hpp"
28#include "grid_algorithm_generic.hpp"
29#include "generic_algorithm_transformation.hpp"
30#include "algo_types.hpp"
31
32#include <regex>
33
34namespace xios
35{
36
37   /// ////////////////////// Dfinitions ////////////////////// ///
38
39   CGrid::CGrid(void)
40      : CObjectTemplate<CGrid>(), CGridAttributes()
41      , isChecked(false), isDomainAxisChecked(false)
42      , vDomainGroup_(), domList_(), isDomListSet(false)
43      , vAxisGroup_(), axisList_(), isAxisListSet(false)
44      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
45      , clientDistribution_(0), isIndexSent(false)
46      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
47            , isCompressible_(false)
48      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
49      , gridSrc_(), order_()
50      , clients()
51   {
52     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
53     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
54     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
55   }
56
57   CGrid::CGrid(const StdString& id)
58      : CObjectTemplate<CGrid>(id), CGridAttributes()
59      , isChecked(false), isDomainAxisChecked(false)
60      , vDomainGroup_(), domList_(), isDomListSet(false)
61      , vAxisGroup_(), axisList_(), isAxisListSet(false)
62      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
63      , clientDistribution_(0), isIndexSent(false)
64      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
65            , isCompressible_(false)
66      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
67      , gridSrc_(), order_()
68      , clients()
69   {
70     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
71     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
72     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
73   }
74
75   CGrid::~CGrid(void)
76   {
77    if (0 != clientDistribution_) delete clientDistribution_;
78   }
79
80   ///---------------------------------------------------------------
81
82   StdString CGrid::GetName(void)    { return StdString("grid"); }
83   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
84   ENodeType CGrid::GetType(void)    { return eGrid; }
85
86
87  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
88  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89  /////////              MEMBER FUNCTION RELATED TO GRID CONSTRUCTION by ELEMNTS AND MANAGEMENT                      /////
90  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92
93
94   CGrid* CGrid::createGrid(CDomain* domain)
95   TRY
96   {
97     std::vector<CDomain*> vecDom(1, domain);
98     std::vector<CAxis*> vecAxis;
99     return createGrid(vecDom, vecAxis);
100   }
101   CATCH
102
103   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
104   TRY
105  {
106      std::vector<CDomain*> vecDom(1, domain);
107      std::vector<CAxis*> vecAxis(1, axis);
108
109      return createGrid(vecDom, vecAxis);
110   }
111   CATCH
112
113   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
114                            const CArray<int,1>& axisDomainOrder)
115   TRY
116   {
117     std::vector<CScalar*> vecScalar;
118     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
119   }
120   CATCH
121
122   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
123                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
124   TRY
125   {
126     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
127   }
128   CATCH
129
130   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
131                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
132   TRY
133   {
134      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
135        ERROR("CGrid* CGrid::createGrid(...)",
136              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
137              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
138
139      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
140      grid->setDomainList(domains);
141      grid->setAxisList(axis);
142      grid->setScalarList(scalars);
143
144      // By default, domains are always the first elements of a grid
145      if (0 == axisDomainOrder.numElements())
146      {
147        int size = domains.size() + axis.size() + scalars.size();
148        int nb = 0;
149        grid->axis_domain_order.resize(size);
150        for (int i = 0; i < size; ++i)
151        {
152          if (i < domains.size())
153          {
154            grid->axis_domain_order(i) = 2;
155            grid->order_.push_back(2) ;
156          }
157          else if ((scalars.size() < (size-nb)) < size)
158          {
159            grid->axis_domain_order(i) = 1;
160            grid->order_.push_back(1) ;
161          }
162          else
163          {
164            grid->axis_domain_order(i) = 0;
165            grid->order_.push_back(0) ;
166          }
167          ++nb;
168        }
169      }
170      else
171      {
172        grid->axis_domain_order.resize(axisDomainOrder.numElements());
173        grid->axis_domain_order = axisDomainOrder;
174        grid->order_.clear() ;
175        for(int i=0; i<axisDomainOrder.numElements();i++) grid->order_.push_back(axisDomainOrder(i)) ;
176
177      }
178     
179 //     grid->solveElementsRefInheritance(true);
180      grid->computeElements() ;
181      return grid;
182   }
183   CATCH
184
185
186   CGrid* CGrid::get(const string& id, bool noError)
187   {
188     const regex r("::");
189     smatch m;
190     if (regex_search(id, m, r))
191     {
192        if (m.size()!=1) ERROR("CGrid* Cgrid::get(string& id)", <<" id = "<<id<< "  -> bad format id, separator :: append more than one time");
193        string fieldId=m.prefix() ;
194        if (fieldId.empty()) ERROR("CGrid* CGrid::get(string& id)", <<" id = "<<id<< "  -> bad format id, field name is empty");
195        string suffix=m.suffix() ;
196        if (!suffix.empty()) ERROR("CGrid* CGrid::get(string& id)", <<" id = "<<id<< "  -> bad format id, suffix is not empty");
197        if (!CField::has(fieldId)) 
198          if (noError)  return nullptr ;
199          else ERROR("CGrid* CGrid::get(string& id)", <<" id = "<<id<< "  -> field Id : < "<<fieldId<<" > doesn't exist");
200        CField* field=CField::get(fieldId) ;
201        return field->getAssociatedGrid() ;
202     }
203     else 
204     {
205       if (noError) if(!CObjectFactory::HasObject<CGrid>(id)) return nullptr ;
206       return CObjectFactory::GetObject<CGrid>(id).get();
207     }
208   }
209   
210   bool CGrid::has(const string& id)
211   {
212     if (CGrid::get(id,true)==nullptr) return false ;
213     else return true ;
214   }
215   
216   CField* CGrid::getFieldFromId(const string& id)
217   {
218     const regex r("::");
219     smatch m;
220     if (regex_search(id, m, r))
221     {
222        if (m.size()!=1) ERROR("CField* CGrid::getFieldFromId(const string& id)", <<" id = "<<id<< "  -> bad format id, separator :: append more than one time");
223        string fieldId=m.prefix() ;
224        if (fieldId.empty()) ERROR("CField* CGrid::getFieldFromId(const string& id)", <<" id = "<<id<< "  -> bad format id, field name is empty");
225        string suffix=m.suffix() ;
226        if (!suffix.empty()) ERROR("CField* CGrid::getFieldFromId(const string& id)", <<" id = "<<id<< "  -> bad format id, suffix is not empty");
227        if (!CField::has(fieldId)) ERROR("CField* CGrid::getFieldFromId(const string& id)", <<" id = "<<id<< "  -> field Id : < "<<fieldId<<" > doesn't exist");
228        return CField::get(fieldId) ;
229     } 
230     else return nullptr ;
231   }
232
233   //----------------------------------------------------------------
234
235   //! Change virtual field group to a new one
236   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
237   TRY
238   {
239      this->vDomainGroup_ = newVDomainGroup;
240   }
241   CATCH_DUMP_ATTR
242
243   //! Change virtual variable group to new one
244   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
245   TRY
246   {
247      this->vAxisGroup_ = newVAxisGroup;
248   }
249   CATCH_DUMP_ATTR
250
251   //! Change virtual variable group to new one
252   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
253   TRY
254   {
255      this->vScalarGroup_ = newVScalarGroup;
256   }
257   CATCH_DUMP_ATTR
258
259   //----------------------------------------------------------------
260
261   CDomainGroup* CGrid::getVirtualDomainGroup() const
262   TRY
263   {
264     return this->vDomainGroup_;
265   }
266   CATCH
267
268   CAxisGroup* CGrid::getVirtualAxisGroup() const
269   TRY
270   {
271     return this->vAxisGroup_;
272   }
273   CATCH
274
275   CScalarGroup* CGrid::getVirtualScalarGroup() const
276   TRY
277   {
278     return this->vScalarGroup_;
279   }
280   CATCH
281
282  ///---------------------------------------------------------------
283
284   CDomain* CGrid::addDomain(const std::string& id)
285   TRY
286   {
287     order_.push_back(2);
288     axis_domain_order.resize(order_.size());
289     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
290     CDomain* domain = vDomainGroup_->createChild(id);
291     isDomListSet=false ;
292     computeElements();
293     return domain ;
294   }
295   CATCH_DUMP_ATTR
296
297   CAxis* CGrid::addAxis(const std::string& id)
298   TRY
299   {
300     order_.push_back(1);
301     axis_domain_order.resize(order_.size());
302     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
303     CAxis* axis=vAxisGroup_->createChild(id);
304     isAxisListSet=false ;
305     computeElements(); 
306     return axis ;
307   }
308   CATCH_DUMP_ATTR
309
310   CScalar* CGrid::addScalar(const std::string& id)
311   TRY
312   {
313     order_.push_back(0);
314     axis_domain_order.resize(order_.size());
315     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
316     CScalar* scalar =  vScalarGroup_->createChild(id);
317     isScalarListSet=false ;
318     computeElements();
319     return scalar;
320   }
321   CATCH_DUMP_ATTR
322
323
324
325
326  /*!
327  \brief Get the list of domain pointers
328  \return list of domain pointers
329  */
330  std::vector<CDomain*> CGrid::getDomains()
331  TRY
332  {
333    setDomainList();
334    std::vector<CDomain*> domList;
335    if (!domList_.empty())
336    {
337      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
338    }
339    return domList;
340  }
341  CATCH_DUMP_ATTR
342
343  /*!
344  \brief Get the list of  axis pointers
345  \return list of axis pointers
346  */
347  std::vector<CAxis*> CGrid::getAxis()
348  TRY
349  {
350    setAxisList();
351    std::vector<CAxis*> aList;
352    if (!axisList_.empty())
353      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
354
355    return aList;
356  }
357  CATCH_DUMP_ATTR
358
359  /*!
360  \brief Get the list of  axis pointers
361  \return list of axis pointers
362  */
363  std::vector<CScalar*> CGrid::getScalars()
364  TRY
365  {
366    setScalarList() ;
367    std::vector<CScalar*> sList;
368    if (!scalarList_.empty())
369      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
370
371    return sList;
372  }
373  CATCH_DUMP_ATTR
374
375  /*!
376  \brief Get domain pointer with index
377  \return domain pointer
378  */
379  CDomain* CGrid::getDomain(int domainIndex)
380  TRY
381  {
382    std::vector<CDomain*> domainListP = this->getDomains();
383    if (domainListP.empty())
384    {
385      ERROR("CGrid::getDomain(int domainIndex)",
386            << "No domain associated to this grid. " << std::endl
387            << "Grid id = " << this->getId());
388    }
389
390    if (domainIndex >= domainListP.size() || (domainIndex < 0))
391      ERROR("CGrid::getDomain(int domainIndex)",
392            << "Domain with the index doesn't exist " << std::endl
393            << "Grid id = " << this->getId() << std::endl
394            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
395
396    return domainListP[domainIndex];
397  }
398  CATCH_DUMP_ATTR
399
400  /*!
401  \brief Get the axis pointer with index
402  \return axis pointer
403  */
404  CAxis* CGrid::getAxis(int axisIndex)
405  TRY
406  {
407    std::vector<CAxis*> axisListP = this->getAxis();
408    if (axisListP.empty())
409    {
410      ERROR("CGrid::getDomain(int axisIndex)",
411            << "No axis associated to this grid. " << std::endl
412            << "Grid id = " << this->getId());
413    }
414
415    if (axisIndex >= axisListP.size() || (axisIndex < 0))
416      ERROR("CGrid::getDomain(int axisIndex)",
417            << "Domain with the index doesn't exist " << std::endl
418            << "Grid id = " << this->getId() << std::endl
419            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
420
421    return axisListP[axisIndex];
422  }
423  CATCH_DUMP_ATTR
424
425  /*!
426  \brief Get the a scalar pointer
427  \return scalar pointer
428  */
429  CScalar* CGrid::getScalar(int scalarIndex)
430  TRY
431  {
432    std::vector<CScalar*> scalarListP = this->getScalars();
433    if (scalarListP.empty())
434    {
435      ERROR("CGrid::getScalar(int scalarIndex)",
436            << "No scalar associated to this grid. " << std::endl
437            << "Grid id = " << this->getId());
438    }
439
440    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
441      ERROR("CGrid::getScalar(int scalarIndex)",
442            << "Scalar with the index doesn't exist " << std::endl
443            << "Grid id = " << this->getId() << std::endl
444            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
445
446    return scalarListP[scalarIndex];
447  }
448  CATCH_DUMP_ATTR
449
450  CDomain* CGrid::getAssociatedDomain(const string& domainId, bool noError)
451  {
452    const regex r("\\[[0-9]*\\]");
453    smatch m;
454    string id=domainId ;
455    int pos=-1 ;
456    if (regex_search(domainId, m, r))
457    {
458        if (m.size()!=1) ERROR("CGrid::getAssociatedDomain(const string& domainId)", <<" domainId = "<<domainId<< "  -> bad format id, separator [] append more than one time");
459        id=m.prefix() ;
460        pos = stoi(m.str(0).substr(1,m.str(0).size()-2)) ;
461    }
462    std::vector<CDomain*> domainList = this->getDomains();
463    if (domainList.empty()) 
464      if (noError) return nullptr ;
465      else ERROR("CGrid::getAssociatedDomain(const string& domainId)", <<"no domain is composing the grid");
466    if (id.empty())
467    {
468      if (pos==-1)
469      {
470        if (domainList.size()==1) return domainList[0] ;
471        else 
472          if (noError) return nullptr ;
473          else ERROR("CGrid::getAssociatedDomain(const string& domainId)", <<"the grid contain more than 1 domain, use [#n] to specify which one must be retrieved");
474      }
475      else
476      {
477        if (domainList.size()>pos) return domainList[pos] ;
478        else if (noError) return nullptr ;
479        else ERROR("CGrid::getAssociatedDomain(const string& domainId)", <<"the position of the requested domain [ pos = "<<pos
480                   <<" ] is greater than the number of domain composing the grid  [ numDomain = "<<domainList.size()<<" ]");
481      }
482    }
483    else
484    {
485      if (pos==-1) 
486      {
487        int nbDomain=0 ;
488        for(int i=0; i<domainList.size();i++) if (domainList[i]->getTemplateId()==id) nbDomain++ ;
489        if (nbDomain>1) 
490          if (noError) return nullptr ;
491          else ERROR("CGrid::getAssociatedDomain(const string& domainId)", <<"no domain with the id = "<<id
492                              <<" is composing the grid") ;
493        if (nbDomain==0) 
494          if (noError) return nullptr ;
495          else ERROR("CGrid::getAssociatedDomain(const string& domainId)", <<"the grid contain more than 1 domain with the id = "
496                               <<id<<" , use [#n] to specify which one must be retrieved") ;
497        for(int i=0; i<domainList.size();i++) if (domainList[i]->getTemplateId()==id) return domainList[i]  ;
498      }
499      else
500      {
501        int currentPos=0 ;
502        for(int i=0; i<domainList.size();i++) 
503        {
504          if (domainList[i]->getTemplateId()==id && pos==currentPos) return domainList[i] ;
505          currentPos++ ;
506        }
507        if (noError) return nullptr ; 
508        else ERROR("CGrid::getAssociatedDomain(const string& domainId)",<<"Cannot find domain with [ id = "<< id <<" ] at [ pos = "<<pos<<" ] in the grid");
509      } 
510    }
511
512    MISSING_RETURN( "CDomain* CGrid::getAssociatedDomain(const string& domainId, bool noError)" );
513    return nullptr;
514  } 
515
516  CAxis* CGrid::getAssociatedAxis(const string& axisId, bool noError)
517  {
518    const regex r("\\[[0-9]*\\]");
519    smatch m;
520    string id=axisId ;
521    int pos=-1 ;
522    if (regex_search(axisId, m, r))
523    {
524        if (m.size()!=1) ERROR("CGrid::getAssociatedAxis(const string& axisId)", <<" axisId = "<<axisId<< "  -> bad format id, separator [] append more than one time");
525        id=m.prefix() ;
526        pos = stoi(m.str(0).substr(1,m.str(0).size()-2)) ;
527    }
528    std::vector<CAxis*> axisList = this->getAxis();
529    if (axisList.empty())
530      if (noError) return nullptr;
531      else ERROR("CGrid::getAssociatedAxis(const string& AxisId)", <<"no axis is composing the grid");
532    if (id.empty())
533    {
534      if (pos==-1)
535      {
536        if (axisList.size()==1) return axisList[0] ;
537        else 
538          if (noError) return nullptr;
539          else ERROR("CGrid::getAssociatedAxis(const string& axisId)", <<"the grid contain more than 1 axis, use [#n] to specify which one must be retrieved");
540      }
541      else
542      {
543        if (axisList.size()>pos) return axisList[pos] ;
544        else
545          if (noError) return nullptr;
546          else ERROR("CGrid::getAssociatedAxis(const string& axisId)", <<"the position of the requested axis [ pos = "<<pos
547                   <<" ] is greater than the number of axis composing the grid  [ numAxis = "<<axisList.size()<<" ]");
548      }
549    }
550    else
551    {
552      if (pos==-1) 
553      {
554        int nbAxis=0 ;
555        for(int i=0; i<axisList.size();i++) if (axisList[i]->getTemplateId()==id) nbAxis++ ;
556        if (nbAxis>1) 
557          if (noError) return nullptr;
558          else ERROR("CGrid::getAssociatedAxis(const string& axisId)", <<"no axis with the id = "<<id
559                              <<" is composing the grid") ;
560        if (nbAxis==0) 
561          if (noError) return nullptr;
562          else ERROR("CGrid::getAssociatedAxis(const string& axisId)", <<"the grid contain more than 1 axis with the id = "
563                               <<id<<" , use [#n] to specify which one must be retrieved") ;
564        for(int i=0; i<axisList.size();i++) if (axisList[i]->getTemplateId()==id) return axisList[i]  ;
565      }
566      else
567      {
568        int currentPos=0 ;
569        for(int i=0; i<axisList.size();i++) 
570        {
571          if (axisList[i]->getTemplateId()==id && pos==currentPos) return axisList[i] ;
572          currentPos++ ;
573        }
574        if (noError) return nullptr;
575        else ERROR("CGrid::getAssociatedAxis(const string& axisId)",<<"Cannot find axis with [ id = "<< id <<" ] at [ pos = "<<pos<<" ] in the grid");
576      } 
577    }
578
579    MISSING_RETURN( "CAxis* CGrid::getAssociatedAxis(const string& axisId, bool noError)" );
580    return nullptr;
581  } 
582
583  CScalar* CGrid::getAssociatedScalar(const string& scalarId, bool noError)
584  {
585    const regex r("\\[[0-9]*\\]");
586    smatch m;
587    string id=scalarId ;
588    int pos=-1 ;
589    if (regex_search(scalarId, m, r))
590    {
591        if (m.size()!=1) ERROR("CGrid::getAssociatedScalar(const string& scalarId)", <<" scalarId = "<<scalarId<< "  -> bad format id, separator [] append more than one time");
592        id=m.prefix() ;
593        pos = stoi(m.str(0).substr(1,m.str(0).size()-2)) ;
594    }
595    std::vector<CScalar*> scalarList = this->getScalars();
596    if (scalarList.empty()) 
597      if (noError) return nullptr;
598      else ERROR("CGrid::getAssociatedScalar(const string& scalarId)", <<"no scalar is composing the grid");
599    if (id.empty())
600    {
601      if (pos==-1)
602      {
603        if (scalarList.size()==1) return scalarList[0] ;
604        else 
605          if (noError) return nullptr;
606          else ERROR("CGrid::getAssociatedScalar(const string& scalarId)", <<"the grid contain more than 1 scalar, use [#n] to specify which one must be retrieved");
607      }
608      else
609      {
610        if (scalarList.size()>pos) return scalarList[pos] ;
611        else 
612          if (noError) return nullptr;
613          else ERROR("CGrid::getAssociatedScalar(const string& scalarId)", <<"the position of the requested scalar [ pos = "<<pos
614                   <<" ] is greater than the number of scalar composing the grid  [ numScalar = "<<scalarList.size()<<" ]");
615      }
616    }
617    else
618    {
619      if (pos==-1) 
620      {
621        int nbScalar=0 ;
622        for(int i=0; i<scalarList.size();i++) if (scalarList[i]->getTemplateId()==id) nbScalar++ ;
623        if (nbScalar>1) 
624          if (noError) return nullptr;
625          else ERROR("CGrid::getAssociatedScalar(const string& scalarId)", <<"no scalar with the id = "<<id
626                              <<" is composing the grid") ;
627        if (nbScalar==0) 
628          if (noError) return nullptr;
629          else ERROR("CGrid::getAssociatedScalar(const string& scalarId)", <<"the grid contain more than 1 scalar with the id = "
630                               <<id<<" , use [#n] to specify which one must be retrieved") ;
631        for(int i=0; i<scalarList.size();i++) if (scalarList[i]->getTemplateId()==id) return scalarList[i]  ;
632      }
633      else
634      {
635        int currentPos=0 ;
636        for(int i=0; i<scalarList.size();i++) 
637        {
638          if (scalarList[i]->getTemplateId()==id && pos==currentPos) return scalarList[i] ;
639          currentPos++ ;
640        }
641        if (noError) return nullptr;
642        else ERROR("CGrid::getAssociatedScalar(const string& scalarId)",<<"Cannot find scalar with [ id = "<< id <<" ] at [ pos = "<<pos<<" ] in the grid");
643      } 
644    }
645
646    MISSING_RETURN( "CScalar* CGrid::getAssociatedScalar(const string& scalarId, bool noError)" );
647    return nullptr;
648  } 
649
650
651  /*!
652  \brief Set domain(s) of a grid from a list
653  \param[in] domains list of domains
654  */
655  void CGrid::setDomainList(const std::vector<CDomain*> domains)
656  TRY
657  {
658    if (isDomListSet) return;
659    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
660    if (!domains.empty() && domList.empty())
661    {
662      for (int i = 0; i < domains.size(); ++i)
663        this->getVirtualDomainGroup()->addChild(domains[i]);
664      domList = this->getVirtualDomainGroup()->getAllChildren();
665    }
666
667    if (!domList.empty())
668    {
669      int sizeDom = domList.size();
670      domList_.resize(sizeDom);
671      for (int i = 0; i < sizeDom; ++i)
672      {
673        domList_[i] = domList[i]->getId();
674      }
675      isDomListSet = true;
676    }
677  }
678  CATCH_DUMP_ATTR
679
680  /*!
681  \brief Set axis(s) of a grid from a list
682  \param[in] axis list of axis
683  */
684  void CGrid::setAxisList(const std::vector<CAxis*> axis)
685  TRY
686  {
687    if (isAxisListSet) return;
688    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
689    if (!axis.empty() && aList.empty())
690    {
691      for (int i = 0; i < axis.size(); ++i)
692        this->getVirtualAxisGroup()->addChild(axis[i]);
693      aList = this->getVirtualAxisGroup()->getAllChildren();
694    }
695
696    if (!aList.empty())
697    {
698      int sizeAxis = aList.size();
699      axisList_.resize(sizeAxis);
700      for (int i = 0; i < sizeAxis; ++i)
701      {
702        axisList_[i] = aList[i]->getId();
703      }
704      isAxisListSet = true;
705    }
706  }
707  CATCH_DUMP_ATTR
708
709  /*!
710  \brief Set scalar(s) of a grid from a list
711  \param[in] scalars list of scalars
712  */
713  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
714  TRY
715  {
716    if (isScalarListSet) return;
717    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
718    if (!scalars.empty() && sList.empty())
719    {
720      for (int i = 0; i < scalars.size(); ++i)
721        this->getVirtualScalarGroup()->addChild(scalars[i]);
722      sList = this->getVirtualScalarGroup()->getAllChildren();
723    }
724
725    if (!sList.empty())
726    {
727      int sizeScalar = sList.size();
728      scalarList_.resize(sizeScalar);
729      for (int i = 0; i < sizeScalar; ++i)
730      {
731        scalarList_[i] = sList[i]->getId();
732      }
733      isScalarListSet = true;
734    }
735  }
736  CATCH_DUMP_ATTR
737
738  /*!
739  \brief Get list of id of domains
740  \return id list of domains
741  */
742  std::vector<StdString> CGrid::getDomainList()
743  TRY
744  {
745    setDomainList();
746    return domList_;
747  }
748  CATCH
749
750  /*!
751  \brief Get list of id of axis
752  \return id list of axis
753  */
754  std::vector<StdString> CGrid::getAxisList()
755  TRY
756  {
757    setAxisList();
758    return axisList_;
759  }
760  CATCH
761
762  /*!
763  \brief Get list of id of scalar
764  \return id list of scalar
765  */
766  std::vector<StdString> CGrid::getScalarList()
767  TRY
768  {
769    setScalarList();
770    return scalarList_;
771  }
772  CATCH
773
774
775  void CGrid::computeElements(void)
776  {
777    const auto& domains = getDomains() ;
778    const auto& axis = getAxis() ;
779    const auto& scalars = getScalars() ;
780    int idxDomain = 0, idxAxis=0 , idxScalar=0 ; 
781 
782    elements_.clear() ;
783    for(auto type : order_)
784    {
785      if      (type == 0) { elements_.push_back({scalars[idxScalar], TYPE_SCALAR, scalars[idxScalar], nullptr, nullptr } ) ; idxScalar++;}
786      else if (type == 1) { elements_.push_back({axis[idxAxis], TYPE_AXIS, nullptr, axis[idxAxis], nullptr}) ; idxAxis++;}
787      else if (type == 2) { elements_.push_back({domains[idxDomain], TYPE_DOMAIN, nullptr, nullptr, domains[idxDomain] }) ; idxDomain++;}       
788    }
789    elementsComputed_ = true ;
790  }
791 
792 
793 /*!
794    Parse a grid, for now, it contains only domain, axis and scalar
795  */
796  void CGrid::parse(xml::CXMLNode& node)
797  TRY
798  {
799    SuperClass::parse(node);
800
801    if (node.goToChildElement())
802    {
803      StdString domainName("domain");
804      StdString axisName("axis");
805      StdString scalarName("scalar");
806      do
807      {
808        if (node.getElementName() == domainName) {
809          order_.push_back(2);
810          this->getVirtualDomainGroup()->parseChild(node);
811        }
812        if (node.getElementName() == axisName) {
813          order_.push_back(1);
814          this->getVirtualAxisGroup()->parseChild(node);
815        }
816        if (node.getElementName() == scalarName) {
817          order_.push_back(0);
818          this->getVirtualScalarGroup()->parseChild(node);
819        }
820      } while (node.goToNextElement());
821      node.goToParentElement();
822    }
823
824    if (!order_.empty())
825    {
826      int sizeOrd = order_.size();
827      axis_domain_order.resize(sizeOrd);
828      for (int i = 0; i < sizeOrd; ++i)
829      {
830        axis_domain_order(i) = order_[i];
831      }
832    }
833
834    setDomainList();
835    setAxisList();
836    setScalarList();
837    computeElements() ;
838   }
839   CATCH_DUMP_ATTR
840
841
842  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
843  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
844  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
845  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
846
847
848
849   StdSize CGrid::getDimension(void)
850   TRY
851   {
852      return getGlobalDimension().size();
853   }
854   CATCH_DUMP_ATTR
855
856   //---------------------------------------------------------------
857
858   StdSize CGrid::getDataSize(void) 
859   TRY
860   {
861     StdSize retvalue = 1;
862     if (!isScalarGrid())
863     {
864       std::vector<int> dataNindex = getClientDistribution()->getDataNIndex();
865       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];       
866     }
867     return retvalue;
868   }
869   CATCH
870   
871   /*!
872    * Get the local data grid size, ie the size of the compressed grid (inside the workflow)
873    * \return The size od the compressed grid
874    */
875    StdSize  CGrid::getLocalDataSize(void) { return getClientDistribution()->getLocalDataSize();}
876
877
878   /*!
879    * Compute the minimum buffer size required to send the attributes to the server(s).
880    *
881    * \return A map associating the server rank with its minimum buffer size.
882    * TODO: Refactor code
883    */
884   std::map<int, StdSize> CGrid::getAttributesBufferSize(CContextClient* client, bool bufferForWriting)
885   TRY
886   {
887     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
888
889     // The grid indexes require a similar size as the actual data
890     std::map<int, StdSize> dataSizes = getDataBufferSize(client, "", bufferForWriting);
891     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
892     for (it = dataSizes.begin(); it != itE; ++it)
893     {
894       it->second += 2 * sizeof(bool);
895       if (it->second > attributesSizes[it->first])
896         attributesSizes[it->first] = it->second;
897     }
898     
899     // Account for the axis attributes
900     std::vector<CAxis*> axisList = getAxis();
901     for (size_t i = 0; i < axisList.size(); ++i)
902     {
903       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client, getGlobalDimension(),getAxisPositionInGrid()[i]);
904       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
905       {
906         it->second += 2 * sizeof(bool);
907         if (it->second > attributesSizes[it->first])
908           attributesSizes[it->first] = it->second;
909       }
910     }
911
912     // Account for the domain attributes
913     std::vector<CDomain*> domList = getDomains();
914     for (size_t i = 0; i < domList.size(); ++i)
915     {
916       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize(client);
917       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
918       {
919         it->second += 2 * sizeof(bool);
920         if (it->second > attributesSizes[it->first])
921           attributesSizes[it->first] = it->second;
922       }
923     }
924
925     return attributesSizes;
926  }
927   CATCH_DUMP_ATTR
928
929   /*!
930    * Compute the minimum buffer size required to send the data.
931    * \param client contextClient used to determine the size of connected receivers
932    * \param id the id used to tag the data
933    * \param bufferForWriting flag indicating if a buffer is used to send data for writing
934    * \return A map associating the sender rank with its minimum buffer size.
935    */
936   std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/, bool bufferForWriting /*= "false"*/)
937   TRY
938   {     
939     // The record index is sometimes sent along with the data but we always
940     // include it in the size calculation for the sake of simplicity
941     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() 
942                                                       + 2 * sizeof(size_t) 
943                                                       + sizeof(size_t);
944
945     std::map<int, StdSize> dataSizes;
946     int receiverSize = client->getRemoteSize();
947     std::map<int,size_t>& dataSizeMap = bufferForWriting ? connectedDataSize_[receiverSize]: connectedDataSizeRead_;
948     std::vector<int>& connectedServerRanks = bufferForWriting ? connectedServerRank_[receiverSize] : connectedServerRankRead_;
949
950     std::map<int, size_t>::const_iterator itEnd = dataSizeMap.end();
951     for (size_t k = 0; k < connectedServerRanks.size(); ++k)
952     {
953       int rank = connectedServerRanks[k];
954       std::map<int, size_t>::const_iterator it = dataSizeMap.find(rank);
955       size_t count = (it != itEnd) ? it->second : 0;
956
957       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
958     }
959
960     return dataSizes;
961   }
962   CATCH_DUMP_ATTR
963
964   size_t CGrid::getGlobalWrittenSize(void)
965   TRY
966   {
967         std::vector<CDomain*> domainP = this->getDomains();
968     std::vector<CAxis*> axisP = this->getAxis();
969     
970     size_t globalGridSize=1 ;
971     for (std::vector<CDomain*>::iterator it=domainP.begin(); it!=domainP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
972     for (std::vector<CAxis*>::iterator it=axisP.begin(); it!=axisP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
973     return globalGridSize ;
974   }
975   CATCH_DUMP_ATTR
976   
977
978   void CGrid::computeAxisPositionInGrid(void)
979   {
980     axisPositionInGrid_.resize(0);
981     int idx = 0;
982     for (int i = 0; i < axis_domain_order.numElements(); ++i)
983     {
984       int elementDimension = axis_domain_order(i);
985       if (1 == elementDimension)
986       {
987         axisPositionInGrid_.push_back(idx);
988         ++idx;
989       }
990       else if (2 == elementDimension) idx += 2;
991     }
992   }
993
994 
995   /*!
996    * Test whether the data defined on the grid can be outputted in a compressed way.
997    *
998    * \return true if and only if a mask was defined for this grid
999    */
1000   bool CGrid::isCompressible(void) const
1001   TRY
1002   {
1003      return isCompressible_;
1004   }
1005   CATCH
1006
1007   //---------------------------------------------------------------
1008
1009   void CGrid::addRelFileCompressed(const StdString& filename)
1010   TRY
1011   {
1012      this->relFilesCompressed.insert(filename);
1013   }
1014   CATCH_DUMP_ATTR
1015
1016   bool CGrid::isWrittenCompressed(const StdString& filename) const
1017   TRY
1018   {
1019      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
1020   }
1021   CATCH
1022
1023   //---------------------------------------------------------------
1024   /*
1025     Find all reference of grid's components and inherite attributes if necessary
1026   */
1027   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
1028   TRY
1029   {
1030     if (this->isDomainAxisChecked) return;
1031
1032     this->solveScalarRef(areAttributesChecked);
1033     this->solveAxisRef(areAttributesChecked);
1034     this->solveDomainRef(areAttributesChecked);     
1035     this->isDomainAxisChecked = areAttributesChecked;
1036   }
1037   CATCH_DUMP_ATTR
1038
1039   /*
1040     Go up hierachy reference and fill in the base reference with attributes of the children
1041     This function should be only used after reading component's attributes from file
1042   */
1043   void CGrid::solveDomainAxisBaseRef()
1044   TRY
1045   {
1046     if (this->hasDomainAxisBaseRef_) return;
1047     // Account for the scalar attributes
1048     std::vector<CScalar*> scalarList = getScalars();
1049     for (size_t i = 0; i < scalarList.size(); ++i)
1050     {
1051       scalarList[i]->setAttributesReference();
1052     }
1053
1054     // Account for the axis attributes
1055     std::vector<CAxis*> axisList = getAxis();
1056     for (size_t i = 0; i < axisList.size(); ++i)
1057     {
1058       axisList[i]->setAttributesReference();
1059     }
1060
1061     // Account for the domain attributes
1062     std::vector<CDomain*> domList = getDomains();
1063     for (size_t i = 0; i < domList.size(); ++i)
1064     {
1065       domList[i]->setAttributesReference();
1066     }
1067
1068     this->hasDomainAxisBaseRef_ = true;
1069   }
1070   CATCH_DUMP_ATTR
1071
1072   void CGrid::checkEligibilityForCompressedOutput()
1073   TRY
1074   {
1075     // We don't check if the mask is valid here, just if a mask has been defined at this point.
1076     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
1077   }
1078   CATCH_DUMP_ATTR
1079
1080   //ym obsolete -> to be removed later
1081   void CGrid::checkMaskIndex(bool doSendingIndex)
1082   TRY
1083   {
1084     CContext* context = CContext::getCurrent();
1085     
1086     if (this->isChecked) return;
1087     this->checkElementsAttributes();
1088     this->isChecked = true;
1089   }
1090   CATCH_DUMP_ATTR
1091
1092
1093   bool CGrid::hasMask() const
1094   TRY
1095   {
1096     return (!mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty() ||
1097             !mask_4d.isEmpty() || !mask_5d.isEmpty() || !mask_6d.isEmpty() || !mask_7d.isEmpty());
1098   }
1099   CATCH
1100
1101   
1102   CArray<bool,1>& CGrid::getMask(void)
1103   {
1104     
1105      if (mask_.isEmpty())
1106      { 
1107        if (!mask_0d.isEmpty()) mask_.reference(CArray<bool,1>(mask_0d.dataFirst(),shape(mask_0d.numElements()), neverDeleteData)) ;
1108        if (!mask_1d.isEmpty()) mask_.reference(CArray<bool,1>(mask_1d.dataFirst(),shape(mask_1d.numElements()), neverDeleteData)) ;
1109        if (!mask_2d.isEmpty()) mask_.reference(CArray<bool,1>(mask_2d.dataFirst(),shape(mask_2d.numElements()), neverDeleteData)) ;
1110        if (!mask_3d.isEmpty()) mask_.reference(CArray<bool,1>(mask_3d.dataFirst(),shape(mask_3d.numElements()), neverDeleteData)) ;
1111        if (!mask_4d.isEmpty()) mask_.reference(CArray<bool,1>(mask_4d.dataFirst(),shape(mask_4d.numElements()), neverDeleteData)) ;
1112        if (!mask_5d.isEmpty()) mask_.reference(CArray<bool,1>(mask_5d.dataFirst(),shape(mask_5d.numElements()), neverDeleteData)) ;
1113        if (!mask_6d.isEmpty()) mask_.reference(CArray<bool,1>(mask_6d.dataFirst(),shape(mask_6d.numElements()), neverDeleteData)) ;
1114        if (!mask_7d.isEmpty()) mask_.reference(CArray<bool,1>(mask_7d.dataFirst(),shape(mask_7d.numElements()), neverDeleteData)) ;
1115      }
1116      return mask_ ;
1117   }
1118
1119 
1120   //---------------------------------------------------------------
1121
1122   void CGrid::solveDomainRef(bool sendAtt)
1123   TRY
1124   {
1125      setDomainList();
1126      std::vector<CDomain*> domListP = this->getDomains();
1127      if (!domListP.empty())
1128        for (int i = 0; i < domListP.size(); ++i) domListP[i]->checkAttributes();
1129   }
1130   CATCH_DUMP_ATTR
1131
1132   //---------------------------------------------------------------
1133
1134   void CGrid::solveAxisRef(bool sendAtt)
1135   TRY
1136   {
1137      setAxisList();
1138      std::vector<CAxis*> axisListP = this->getAxis();
1139      if (!axisListP.empty())
1140        for (int i = 0; i < axisListP.size(); ++i)  axisListP[i]->checkAttributes();
1141   }
1142   CATCH_DUMP_ATTR
1143
1144   //---------------------------------------------------------------
1145
1146   void CGrid::solveScalarRef(bool sendAtt)
1147   TRY
1148   {
1149      setScalarList();
1150      std::vector<CScalar*> scalarListP = this->getScalars();
1151      if (!scalarListP.empty())
1152        for (int i = 0; i < scalarListP.size(); ++i) scalarListP[i]->checkAttributes() ;
1153   }
1154   CATCH_DUMP_ATTR
1155
1156
1157    //---------------------------------------------------------------
1158   CDistributionClient* CGrid::getClientDistribution()
1159   TRY
1160   {
1161     if (!computeClientDistribution_done_) computeClientDistribution() ;
1162     return clientDistribution_;
1163   }
1164   CATCH_DUMP_ATTR
1165   
1166   void CGrid::computeClientDistribution(void)
1167   {
1168     if (computeClientDistribution_done_) return ;
1169     else computeClientDistribution_done_ = true ;
1170
1171     CContext* context = CContext::getCurrent();
1172     int rank = context-> getIntraCommRank();
1173     clientDistribution_ = new CDistributionClient(rank, this);
1174   }
1175
1176
1177  bool CGrid::isDataDistributed(void) 
1178  { 
1179    return getClientDistribution()->isDataDistributed() ;
1180  }
1181
1182 
1183
1184   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
1185   TRY
1186   {
1187     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
1188     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
1189     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
1190
1191     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
1192     {
1193       CDomain* domain = CDomain::createDomain();
1194       domain->duplicateAttributes(domainSrcTmp[idx]);
1195       domain->duplicateTransformation(domainSrcTmp[idx]);
1196       domain->solveRefInheritance(true);
1197       domain->solveInheritanceTransformation();
1198       domainSrc.push_back(domain);
1199     }
1200
1201     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
1202     {
1203       CAxis* axis = CAxis::createAxis();
1204       axis->duplicateAttributes(axisSrcTmp[idx]);
1205       axis->duplicateTransformation(axisSrcTmp[idx]);
1206       axis->solveRefInheritance(true);
1207       axis->solveInheritanceTransformation();
1208       axisSrc.push_back(axis);
1209     }
1210
1211     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
1212     {
1213       CScalar* scalar = CScalar::createScalar();
1214       scalar->duplicateAttributes(scalarSrcTmp[idx]);
1215       scalar->duplicateTransformation(scalarSrcTmp[idx]);
1216       scalar->solveRefInheritance(true);
1217       scalar->solveInheritanceTransformation();
1218       scalarSrc.push_back(scalar);
1219     }
1220
1221      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
1222
1223      return grid;
1224   }
1225   CATCH
1226
1227   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1228                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1229   TRY
1230   {
1231      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1232        ERROR("CGrid* CGrid::generateId(...)",
1233              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1234              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1235
1236      std::ostringstream id;
1237
1238      if (domains.empty() && axis.empty() && !scalars.empty())
1239        id << "__scalar_";
1240
1241      if (0 != (domains.size() + axis.size() + scalars.size()))
1242      {
1243        id << "__grid";
1244
1245        if (0 == axisDomainOrder.numElements())
1246        {
1247          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
1248          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
1249          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
1250        }
1251        else
1252        {
1253          size_t iDomain = 0, iAxis = 0, iScalar = 0;
1254          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
1255          {
1256            if (2 == axisDomainOrder(i))
1257              id << "_" << domains[iDomain++]->getId();
1258            else if (1 == axisDomainOrder(i))
1259              id << "_" << axis[iAxis++]->getId();
1260            else
1261              id << "_" << scalars[iScalar++]->getId();
1262          }
1263        }
1264
1265        id << "__";
1266      }
1267
1268      return id.str();
1269   }
1270   CATCH
1271
1272   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
1273   TRY
1274   {
1275     StdString idSrc  = gridSrc->getId();
1276     StdString idDest = gridDest->getId();
1277
1278     std::ostringstream id;
1279     id << idSrc << "__" << idDest;
1280
1281     return id.str();
1282   }
1283   CATCH
1284
1285
1286   //----------------------------------------------------------------
1287
1288   
1289 
1290 
1291  /*
1292     Compute on the fly the global dimension of a grid with its elements
1293     \param[in/out] globalDim global dimension of grid
1294     \param[in] domains list of its domains
1295     \param[in] axiss list of its axis
1296     \param[in] scalars list of its scalars
1297     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
1298     \return The dimension of which we do distribution (often for server)
1299  */
1300  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
1301                                        const std::vector<CDomain*> domains,
1302                                        const std::vector<CAxis*> axis,
1303                                        const std::vector<CScalar*> scalars,
1304                                        const CArray<int,1>& axisDomainOrder)
1305  TRY
1306 {
1307 //   globalDim.resize(domains.size()*2+axis.size()+scalars.size());
1308    globalDim.resize(domains.size()*2+axis.size());
1309    int positionDimensionDistributed = 1;
1310    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
1311    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
1312    {
1313      if (2 == axisDomainOrder(i))
1314      {
1315        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
1316        {
1317          positionDimensionDistributed = idx;
1318        }
1319        else
1320        {
1321          positionDimensionDistributed = idx +1;
1322        }
1323
1324        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
1325        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
1326
1327        ++idxDomain;
1328        idx += 2;
1329      }
1330      else if (1 == axisDomainOrder(i))
1331      {
1332        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
1333        ++idxAxis;
1334        ++idx;
1335      }
1336      else
1337      {
1338//        globalDim[idx] = 1;
1339        ++idxScalar;
1340//        ++idx;
1341      }
1342    }
1343
1344    return positionDimensionDistributed;
1345  }
1346  CATCH_DUMP_ATTR
1347
1348  // Retrieve the global dimension of grid
1349  std::vector<int> CGrid::getGlobalDimension()
1350  TRY
1351  {
1352    std::vector<int> globalDim;
1353    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
1354
1355    return globalDim;
1356  }
1357  CATCH_DUMP_ATTR
1358
1359  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
1360  int CGrid::getDistributedDimension()
1361  TRY
1362  {
1363    std::vector<int> globalDim;
1364    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
1365  }
1366  CATCH_DUMP_ATTR
1367
1368  bool CGrid::isScalarGrid() const
1369  TRY
1370  {
1371    return (axisList_.empty() && domList_.empty());
1372  }
1373  CATCH
1374
1375  /*!
1376    Verify whether one server need to write data
1377    There are some cases on which one server has nodata to write. For example, when we
1378    just only want to zoom on a domain.
1379  */
1380  bool CGrid::doGridHaveDataToWrite()
1381  TRY
1382  {
1383     return (0 != getGridLocalElements()->getView(CElementView::FULL)->getSize());
1384  }
1385  CATCH_DUMP_ATTR
1386
1387 
1388  bool CGrid::doGridHaveDataDistributed(CContextClient* client)
1389  TRY
1390  {
1391    // This function is now useless because it will return false only if server and client size are equal to 1
1392    // to be seriously check in future
1393
1394    if (isScalarGrid()) return false;
1395    else if (0 != client)
1396    {
1397      return  (isDataDistributed() ||  (1 != client->getRemoteSize()) || (1 != client->getRemoteSize()));
1398    }
1399    else
1400      return isDataDistributed();   
1401  }
1402  CATCH_DUMP_ATTR
1403
1404   /*!
1405   \brief Dispatch event received from client
1406      Whenever a message is received in buffer of server, it will be processed depending on
1407   its event type. A new event type should be added in the switch list to make sure
1408   it processed on server side.
1409   \param [in] event: Received message
1410   */
1411  bool CGrid::dispatchEvent(CEventServer& event)
1412  TRY
1413  {
1414
1415    if (SuperClass::dispatchEvent(event)) return true;
1416    else
1417    {
1418      switch(event.type)
1419      {
1420         case EVENT_ID_ADD_DOMAIN :
1421           recvAddDomain(event);
1422           return true;
1423           break;
1424
1425         case EVENT_ID_ADD_AXIS :
1426           recvAddAxis(event);
1427           return true;
1428           break;
1429
1430         case EVENT_ID_ADD_SCALAR :
1431           recvAddScalar(event);
1432           return true;
1433           break;
1434
1435         case EVENT_ID_SEND_MASK :
1436           recvMask(event);
1437           return true;
1438           break;
1439        default :
1440          ERROR("bool CGrid::dispatchEvent(CEventServer& event)",
1441                << "Unknown Event");
1442          return false;
1443      }
1444    }
1445  }
1446  CATCH
1447
1448 
1449
1450  void CGrid::sendGridToFileServer(CContextClient* client, bool inOut)
1451  {
1452    if (sendGridToFileServer_done_.count(client)!=0) return ;
1453    else sendGridToFileServer_done_.insert(client) ;
1454
1455    StdString gridDefRoot("grid_definition");
1456    CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1457    gridPtr->sendCreateChild(this->getId(),client);
1458    this->sendAllAttributesToServer(client);
1459    distributeGridToServer(client, inOut) ;
1460  }
1461
1462
1463  void CGrid::sendGridToCouplerOut(CContextClient* client, const string& fieldId)
1464  {
1465    if (sendGridToCouplerOut_done_.count(client)!=0) return ;
1466    else sendGridToCouplerOut_done_.insert(client) ;
1467    this->sendAllAttributesToServer(client, getCouplingAlias(fieldId));
1468    distributeGridToServer(client, false, fieldId) ;
1469  }
1470
1471
1472  void CGrid::distributeGridToServer(CContextClient* client, bool inOut, const string& fieldId)
1473  {
1474    CContext* context = CContext::getCurrent();
1475    bool isCoupling = !fieldId.empty() ;
1476    // simple Distribution for now
1477    // distribute over the fisrt element except if it is a scalar
1478    auto& elements = getElements() ;
1479    int posDistributed = 0 ;
1480    for(auto& element : elements)
1481    {
1482      if (element.type==TYPE_DOMAIN) break ;
1483      else if (element.type==TYPE_AXIS) break ;
1484      else if (element.type==TYPE_SCALAR) posDistributed++ ;
1485    }
1486    if (posDistributed==elements.size()) posDistributed=0 ; // grid composed only of scalar
1487   
1488    vector<shared_ptr<CLocalView>> localViews ;
1489    vector<shared_ptr<CLocalView>> workflowView ;
1490    vector<shared_ptr<CDistributedView>> remoteViews ;
1491
1492    for(int i=0 ; i<elements.size() ; i++)
1493    {
1494      if (elements[i].type==TYPE_DOMAIN) 
1495      { 
1496         CDomain* domain = (CDomain*) elements[i].ptr ;
1497         domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
1498         remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ;
1499         localViews.push_back(domain->getLocalView(CElementView::FULL)) ;
1500         workflowView.push_back(domain->getLocalView(CElementView::WORKFLOW)) ;
1501      }
1502      else if (elements[i].type==TYPE_AXIS)
1503      {
1504        CAxis* axis = (CAxis*) elements[i].ptr ;
1505        axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
1506        remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ;
1507        localViews.push_back(axis->getLocalView(CElementView::FULL)) ;
1508        workflowView.push_back(axis->getLocalView(CElementView::WORKFLOW)) ;
1509      }
1510      else if (elements[i].type==TYPE_SCALAR)
1511      {
1512        CScalar* scalar = (CScalar*) elements[i].ptr ;
1513        scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::ROOT : EDistributionType::NONE) ;
1514        remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ;
1515        localViews.push_back(scalar->getLocalView(CElementView::FULL)) ;
1516        workflowView.push_back(scalar->getLocalView(CElementView::WORKFLOW)) ;
1517      }
1518    }
1519   
1520    // CGridClientServerRemoteConnector : workflowView is added to avoid spurious optimisation with only the fullview
1521    auto gridRemoteConnector = make_shared<CGridClientServerRemoteConnector>(localViews, workflowView, remoteViews, context->getIntraComm(), client->getRemoteSize()) ;
1522    gridRemoteConnector->computeConnectorOut() ;
1523   
1524    shared_ptr<CGridClientServerRemoteConnector> gridRemoteConnectorIn ;
1525    if (inOut)
1526    {
1527      gridRemoteConnectorIn = make_shared<CGridClientServerRemoteConnector>(localViews, workflowView, remoteViews, context->getIntraComm(), client->getRemoteSize()) ;
1528      gridRemoteConnectorIn->computeConnectorIn() ;
1529    }
1530    else gridRemoteConnectorIn = gridRemoteConnector ;
1531
1532
1533    vector<shared_ptr<CScattererConnector>> scattererConnectors ;
1534    shared_ptr<CScattererConnector> scattererConnector;
1535    for(int i=0 ; i<elements.size() ; i++)
1536    {
1537      if (elements[i].type==TYPE_DOMAIN) 
1538      { 
1539        CDomain* domain = (CDomain*) elements[i].ptr ;
1540        if (isCoupling) domain->distributeToServer(client, inOut, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i),
1541                                                   scattererConnector,  domain->getCouplingAlias(fieldId,i)) ;
1542        else 
1543        {
1544          sendAddDomain(domain->getId(),client) ;
1545          domain->distributeToServer(client, inOut, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i), scattererConnector) ;
1546        }
1547        scattererConnectors.push_back(scattererConnector) ;
1548      }
1549      else if (elements[i].type==TYPE_AXIS)
1550      {
1551        CAxis* axis = (CAxis*) elements[i].ptr ;
1552        if (isCoupling) axis->distributeToServer(client, inOut, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i),
1553                                                 scattererConnector,  axis->getCouplingAlias(fieldId,i)) ;
1554        else 
1555        {
1556          sendAddAxis(axis->getId(),client) ;
1557          axis->distributeToServer(client, inOut, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i), scattererConnector) ;
1558        }
1559        scattererConnectors.push_back(scattererConnector) ;
1560      }
1561      else if (elements[i].type==TYPE_SCALAR)
1562      {
1563        CScalar* scalar = (CScalar*) elements[i].ptr ;
1564        if (isCoupling) scalar->distributeToServer(client, inOut, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i),
1565                                                   scattererConnector,  scalar->getCouplingAlias(fieldId,i)) ;
1566        else 
1567        {
1568          sendAddScalar(scalar->getId(),client) ;
1569          scalar->distributeToServer(client, inOut, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i), scattererConnector) ;
1570        }
1571        scattererConnectors.push_back(scattererConnector) ;
1572      }
1573    }
1574
1575    auto gridScattererConnector = make_shared<CGridScattererConnector>(scattererConnectors) ;
1576    shared_ptr<CGridLocalConnector> workflowToFull = getGridLocalElements()->getConnector(CElementView::WORKFLOW, CElementView::FULL) ;
1577    CArray<bool,1> maskIn(workflowToFull->getSrcSize()) ;
1578    CArray<bool,1> maskOut(workflowToFull->getDstSize()) ;
1579    maskIn = true ;
1580    workflowToFull->transfer(maskIn,maskOut,false) ;
1581
1582    CEventClient event(getType(), EVENT_ID_SEND_MASK);
1583    CMessage message ;
1584    if (isCoupling) message<<getCouplingAlias(fieldId) ;
1585    else message<<getId() ; 
1586    gridScattererConnector->transfer(maskOut, client, event, message) ;
1587   
1588    vector<shared_ptr<CScattererConnector>> clientToServerConnectors ;
1589    vector<shared_ptr<CGathererConnector>>  clientFromServerConnectors ;
1590    for(auto& element : elements)
1591    {
1592      if (element.type==TYPE_DOMAIN) 
1593      { 
1594         clientToServerConnectors.push_back(element.domain->getClientToServerConnector(client)) ;
1595         if (inOut) clientFromServerConnectors.push_back(element.domain->getClientFromServerConnector(client)) ;
1596      }
1597      else if (element.type==TYPE_AXIS)
1598      {
1599        clientToServerConnectors.push_back(element.axis->getClientToServerConnector(client)) ;
1600        if (inOut) clientFromServerConnectors.push_back(element.axis->getClientFromServerConnector(client)) ;
1601
1602      }
1603      else if (element.type==TYPE_SCALAR)
1604      {
1605        clientToServerConnectors.push_back(element.scalar->getClientToServerConnector(client)) ;
1606        if (inOut) clientFromServerConnectors.push_back(element.scalar->getClientFromServerConnector(client)) ;
1607      }
1608    }
1609   
1610    // compute the grid clientToServerConnector to send flux from client to servers
1611    clientToServerConnector_[client] = make_shared<CGridScattererConnector>(clientToServerConnectors) ;
1612    if (inOut) clientFromServerConnector_[client] = make_shared<CGridGathererConnector>(clientFromServerConnectors) ;
1613
1614  }
1615
1616
1617  void CGrid::recvMask(CEventServer& event)
1618  {
1619    string gridId;
1620    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> gridId  ;
1621    get(gridId)->receiveMask(event);
1622  }
1623 
1624  void CGrid::receiveMask(CEventServer& event)
1625  {
1626    vector<shared_ptr<CGathererConnector>> gathererConnectors ;
1627    vector<shared_ptr<CLocalView>> fullViews ;
1628
1629    for(auto& element : getElements())
1630    {
1631      if (element.type==TYPE_DOMAIN) 
1632      {
1633        gathererConnectors.push_back(element.domain->getGathererConnector());
1634        fullViews.push_back(element.domain->getLocalElement()->getView(CElementView::FULL));
1635       
1636      }
1637      else if (element.type==TYPE_AXIS)
1638      {
1639       gathererConnectors.push_back(element.axis->getGathererConnector());
1640       fullViews.push_back(element.axis->getLocalElement()->getView(CElementView::FULL));
1641      }
1642      else if (element.type==TYPE_SCALAR) 
1643      {
1644        gathererConnectors.push_back(element.scalar->getGathererConnector());
1645        fullViews.push_back(element.scalar->getLocalElement()->getView(CElementView::FULL));
1646      }
1647    }
1648    auto gridGathererConnector = make_shared<CGridGathererConnector>(gathererConnectors) ;
1649    auto gridMaskConnector = make_shared<CGridMaskConnector>(fullViews) ;
1650
1651    CArray<bool,1> maskOut ;
1652    gridGathererConnector->transfer_or(event,maskOut) ;
1653    gridMaskConnector->computeConnector(maskOut) ;
1654
1655    CContextClient* client = event.getContextServer()->getAssociatedClient() ;
1656    int i=0 ;
1657    for(auto& element : getElements())
1658    {
1659      if (element.type==TYPE_DOMAIN) element.domain->setServerMask(gridMaskConnector->getElementMask(i),client);
1660      else if (element.type==TYPE_AXIS) element.axis->setServerMask(gridMaskConnector->getElementMask(i),client);
1661      else if (element.type==TYPE_SCALAR) element.scalar->setServerMask(gridMaskConnector->getElementMask(i),client);
1662      i++ ;
1663    }
1664  }
1665
1666  string CGrid::getCouplingAlias(const string& fieldId)
1667  {
1668    return "_grid_of_"+fieldId;
1669  }
1670
1671  void CGrid::makeAliasForCoupling(const string& fieldId)
1672  {
1673    string gridId=getCouplingAlias(fieldId) ;
1674    createAlias(gridId) ;
1675
1676    auto& elements = getElements() ;
1677    for(int i=0 ; i<elements.size() ; i++)
1678    {
1679      if (elements[i].type==TYPE_DOMAIN) elements[i].domain->makeAliasForCoupling(fieldId, i);
1680      else if (elements[i].type==TYPE_AXIS) elements[i].axis->makeAliasForCoupling(fieldId, i);
1681      else if (elements[i].type==TYPE_SCALAR) elements[i].scalar->makeAliasForCoupling(fieldId, i);
1682    }
1683  }
1684
1685   /*!
1686   \brief Send a message to create a domain on server side
1687   \param[in] id String identity of domain that will be created on server
1688   */
1689   void CGrid::sendAddDomain(const string& id, CContextClient* contextClient)
1690   TRY
1691  {
1692      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN, contextClient);
1693   }
1694   CATCH_DUMP_ATTR
1695
1696   /*!
1697   \brief Send a message to create an axis on server side
1698   \param[in] id String identity of axis that will be created on server
1699   */
1700   void CGrid::sendAddAxis(const string& id, CContextClient* contextClient)
1701   TRY
1702   {
1703      sendAddItem(id, (int)EVENT_ID_ADD_AXIS, contextClient);
1704   }
1705   CATCH_DUMP_ATTR
1706
1707   /*!
1708   \brief Send a message to create a scalar on server side
1709   \param[in] id String identity of scalar that will be created on server
1710   */
1711   void CGrid::sendAddScalar(const string& id, CContextClient* contextClient)
1712   TRY
1713   {
1714      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR, contextClient);
1715   }
1716   CATCH_DUMP_ATTR
1717
1718   /*!
1719   \brief Receive a message annoucing the creation of a domain on server side
1720   \param[in] event Received event
1721   */
1722   void CGrid::recvAddDomain(CEventServer& event)
1723   TRY
1724   {
1725
1726      CBufferIn* buffer = event.subEvents.begin()->buffer;
1727      string id;
1728      *buffer >> id;
1729      get(id)->recvAddDomain(*buffer);
1730   }
1731   CATCH
1732
1733   /*!
1734   \brief Receive a message annoucing the creation of a domain on server side
1735   \param[in] buffer Buffer containing message
1736   */
1737   void CGrid::recvAddDomain(CBufferIn& buffer)
1738   TRY
1739   {
1740      string id;
1741      buffer >> id;
1742      addDomain(id);
1743   }
1744   CATCH_DUMP_ATTR
1745
1746   /*!
1747   \brief Receive a message annoucing the creation of an axis on server side
1748   \param[in] event Received event
1749   */
1750   void CGrid::recvAddAxis(CEventServer& event)
1751   TRY
1752   {
1753
1754      CBufferIn* buffer = event.subEvents.begin()->buffer;
1755      string id;
1756      *buffer >> id;
1757      get(id)->recvAddAxis(*buffer);
1758   }
1759   CATCH
1760
1761   /*!
1762   \brief Receive a message annoucing the creation of an axis on server side
1763   \param[in] buffer Buffer containing message
1764   */
1765   void CGrid::recvAddAxis(CBufferIn& buffer)
1766   TRY
1767   {
1768      string id;
1769      buffer >> id;
1770      addAxis(id);
1771   }
1772   CATCH_DUMP_ATTR
1773
1774   /*!
1775   \brief Receive a message annoucing the creation of an scalar on server side
1776   \param[in] event Received event
1777   */
1778   void CGrid::recvAddScalar(CEventServer& event)
1779   TRY
1780   {
1781
1782      CBufferIn* buffer = event.subEvents.begin()->buffer;
1783      string id;
1784      *buffer >> id;
1785      get(id)->recvAddScalar(*buffer);
1786   }
1787   CATCH
1788
1789   /*!
1790   \brief Receive a message annoucing the creation of an scalar on server side
1791   \param[in] buffer Buffer containing message
1792   */
1793   void CGrid::recvAddScalar(CBufferIn& buffer)
1794   TRY
1795   {
1796      string id;
1797      buffer >> id;
1798      addScalar(id);
1799   }
1800   CATCH_DUMP_ATTR
1801
1802  /*!
1803  \brief Check if all elements of the grid are complete
1804  Before make any grid processing, we must be sure that all grid information elements have
1805  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1806  other context (coupling)
1807  */
1808  bool CGrid::isCompleted(void)
1809  {
1810    setDomainList();
1811    for (auto domainId : domList_) if (!CDomain::get(domainId)->isCompleted()) return false ;
1812    setAxisList() ;
1813    for (auto axisId : axisList_) if (!CAxis::get(axisId)->isCompleted()) return false ;
1814    setScalarList() ;
1815    for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->isCompleted()) return false ;
1816    return true ;
1817  }
1818
1819  /*!
1820  \brief impose that all elements of the grid are complete
1821  Before make any grid processing, we must be sure that all grid information elements have
1822  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1823  other context (coupling)
1824  */
1825  void CGrid::setCompleted(void)
1826  {
1827    setDomainList();
1828    for (auto domainId : domList_) CDomain::get(domainId)->setCompleted() ;
1829    setAxisList() ;
1830    for (auto axisId : axisList_) CAxis::get(axisId)->setCompleted() ;
1831    setScalarList() ;
1832    for (auto scalarId : scalarList_) CScalar::get(scalarId)->setCompleted() ;
1833  }
1834
1835/*!
1836  \brief impose that all elements of the grid are incomplete
1837  Before make any grid processing, we must be sure that all grid information elements have
1838  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1839  other context (coupling)
1840  */
1841  void CGrid::unsetCompleted(void)
1842  {
1843    setDomainList();
1844    for (auto domainId : domList_) CDomain::get(domainId)->unsetCompleted() ;
1845    setAxisList() ;
1846    for (auto axisId : axisList_) CAxis::get(axisId)->unsetCompleted() ;
1847    setScalarList() ;
1848    for (auto scalarId : scalarList_) CScalar::get(scalarId)->unsetCompleted() ;
1849  }
1850
1851  /*!
1852  \brief Solve domain and axis references
1853  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1854  all attributes from their parents, they should be processed with this function
1855  \param[in] apply inherit all attributes of parents (true)
1856  */
1857  void CGrid::solveElementsRefInheritance(bool apply)
1858  TRY
1859  {
1860    setDomainList();
1861    for (auto domainId : domList_)
1862    {
1863      CDomain* pDom = CDomain::get(domainId);
1864      pDom->solveRefInheritance(apply);
1865      if (apply) pDom->solveInheritanceTransformation();
1866    }
1867
1868    setAxisList();
1869    for (auto axisId : axisList_)
1870    {
1871      CAxis* pAxis = CAxis::get(axisId);
1872      pAxis->solveRefInheritance(apply);
1873      if (apply) pAxis->solveInheritanceTransformation();
1874    }
1875
1876    setScalarList();
1877    for (auto scalarId : scalarList_)
1878    {
1879      CScalar* pScalar = CScalar::get(scalarId);
1880      pScalar->solveRefInheritance(apply);
1881      if (apply) pScalar->solveInheritanceTransformation();
1882    }
1883  }
1884  CATCH_DUMP_ATTR
1885
1886  bool CGrid::activateFieldWorkflow(CGarbageCollector& gc)
1887  TRY
1888  {
1889    setDomainList();
1890    for (auto domainId : domList_)
1891    {
1892      CDomain* pDom = CDomain::get(domainId);
1893      bool ret = pDom->activateFieldWorkflow(gc);
1894      if (!ret) return false ;
1895    }
1896
1897    setAxisList();
1898    for (auto axisId : axisList_)
1899    {
1900      CAxis* pAxis = CAxis::get(axisId);
1901      bool ret = pAxis->activateFieldWorkflow(gc);
1902      if (!ret) return false ;
1903    }
1904
1905    setScalarList();
1906    for (auto scalarId : scalarList_)
1907    {
1908      CScalar* pScalar = CScalar::get(scalarId);
1909      bool ret = pScalar->activateFieldWorkflow(gc);
1910      if (!ret) return false ;
1911    }
1912    return true ;
1913  }
1914  CATCH_DUMP_ATTR
1915
1916 /*!
1917  \brief check attributes of all elements of the grid
1918  */
1919  void CGrid::checkElementsAttributes(void)
1920  TRY
1921  {
1922    setDomainList();
1923    for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes();
1924
1925    setAxisList();
1926    for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes();
1927   
1928    setScalarList();
1929    for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes();
1930  }
1931  CATCH_DUMP_ATTR
1932
1933
1934
1935//**********************************************************
1936//**************   New transformation method  **************
1937//**********************************************************
1938
1939  std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > 
1940  CGrid::buildTransformationGraph(CGarbageCollector& gc, bool isSource, CGrid* gridSrc, double detectMissingValues, double defaultValue, CGrid*& newGrid, bool graphEnabled, CField* field)
1941  TRY
1942  {
1943    static bool transformationGoing = false;
1944    registerAlgorithmTransformation() ; // needed to enable self-registration of the transformations
1945                                        // big mystery why it doesn't work witout that...
1946                                        // problem with the linker ??
1947
1948    std::shared_ptr<CFilter> inputFilter = std::shared_ptr<CPassThroughFilter>(new CPassThroughFilter(gc));
1949    std::shared_ptr<CFilter> outputFilter = inputFilter ;
1950
1951
1952    string newId ;
1953    if (gridSrc!=nullptr) newId = gridSrc->getId() + " --> " + this->getId()  ;
1954    else newId = " --> " + this->getId()  ;
1955    bool isNewGrid ;
1956    if (CGrid::has(newId))
1957    {
1958      info(100)<<"Retrive existing grid : "<<newId<<endl ;
1959      newGrid = CGrid::get(newId);
1960      isNewGrid = false ;
1961    }
1962    else 
1963    {
1964      info(100)<<"Create new grid : "<<newId<<endl ;
1965      newGrid = CGrid::create(newId) ;
1966      isNewGrid = true ;
1967    }
1968
1969    bool hadTransform=false ;
1970    bool hasTransform=false ;
1971    bool hasRemainTransform=false ;
1972    shared_ptr<CGenericAlgorithmTransformation> algo ;
1973    int pos ;
1974
1975    for(int i=0 ; i<elements_.size(); i++)
1976    {
1977      CTransformationPaths transformationPath ;
1978      auto dstElement = elements_[i] ;
1979
1980      if (dstElement.type==TYPE_DOMAIN)      transformationPath = dstElement.domain->getTransformationPaths() ;
1981      else if (dstElement.type==TYPE_AXIS)   transformationPath = dstElement.axis->getTransformationPaths() ;
1982      else if (dstElement.type==TYPE_SCALAR) transformationPath = dstElement.scalar->getTransformationPaths() ;
1983
1984      SElement srcElement  ;
1985     
1986      CTransformationPaths testTransformationPath(transformationPath) ;
1987      testTransformationPath.mergePaths() ;
1988
1989      if (testTransformationPath.hasTransform())
1990      { 
1991        if (gridSrc==nullptr) srcElement = this->elements_[i] ;
1992        else srcElement = gridSrc->elements_[i] ;
1993
1994        if (gridSrc==nullptr) transformationPath.mergePaths() ;
1995        else
1996        { 
1997          if (srcElement.type==TYPE_DOMAIN)      transformationPath.mergePaths(srcElement.domain->getTransformationPaths()) ;
1998          else if (srcElement.type==TYPE_AXIS)   transformationPath.mergePaths(srcElement.axis->getTransformationPaths()) ;
1999          else if (srcElement.type==TYPE_SCALAR) transformationPath.mergePaths(srcElement.scalar->getTransformationPaths()) ;
2000        }
2001      }
2002      else
2003      {
2004        srcElement = this->elements_[i] ;
2005        transformationPath.mergePaths() ;
2006      } 
2007
2008      hasTransform=transformationPath.hasTransform()  ;
2009     
2010      if (hasTransform && !hadTransform)
2011      {
2012        pos=i ;
2013        EElement dstElementType=transformationPath.getNextElementType() ;
2014        string dstElementId=transformationPath.getNextElementId() ;
2015        string srcElementId=transformationPath.getNextElementSrcId() ;
2016        auto transType = transformationPath.getNextTransformationType() ;
2017        auto transId = transformationPath.getNextTransformationId() ;
2018
2019        CGrid* tmpGridSrc=CGrid::create(); // source grid
2020        if (srcElement.type==TYPE_DOMAIN)      tmpGridSrc->addDomain(srcElement.domain->getId()) ;
2021        else if (srcElement.type==TYPE_AXIS)   tmpGridSrc->addAxis(srcElement.axis->getId()) ;
2022        else if (srcElement.type==TYPE_SCALAR) tmpGridSrc->addScalar(srcElement.scalar->getId()) ;
2023        // WARNING -> suppress checkElement attribute ? What append ?
2024        // tmpGridSrc->checkElementsAttributes() ;
2025        CGrid* tmpGridDst=CGrid::create(); // destination Grid
2026        map<int,int> posInGrid={{0,0}} ;
2027               
2028        info(100)<<"--> New transform from "<<srcElementId<<" to "<<dstElementId<<endl ;
2029        if (dstElementType==EElement::DOMAIN)
2030        {
2031          CDomain* dstDomain ;
2032          CDomain* lastDstDomain ;
2033          bool isGenerate=false ;
2034   
2035          do 
2036          {
2037
2038            if (CDomain::has(dstElementId)) 
2039            {
2040              dstDomain = CDomain::get(dstElementId) ;
2041              info(100)<<"Retrive existing domain : "<<dstElementId<<endl ;
2042            }
2043            else
2044            {
2045              dstDomain = CDomain::create() ;
2046              dstDomain->createAlias(dstElementId) ;
2047              info(100)<<"Create new domain : "<<dstDomain->getId()<<" with alias : "<<dstElementId<<endl ;
2048
2049              if (isGenerate) 
2050              {
2051                dstDomain->duplicateAttributes(lastDstDomain) ;
2052                dstDomain->setTemplateId(lastDstDomain) ;
2053              }
2054              else if (srcElementId=="" && srcElement.type==TYPE_DOMAIN) 
2055              {
2056                dstDomain->duplicateAttributes(srcElement.domain) ; // make a copy
2057                dstDomain->setTemplateId(srcElement.domain) ;
2058              }
2059              else 
2060              {
2061                dstDomain->duplicateAttributes(dstElement.domain) ; // make a copy
2062                dstDomain->setTemplateId(dstElement.domain) ;
2063              }
2064              CTransformation<CDomain>* transformation = CTransformation<CDomain>::createTransformation(transType,"") ;
2065              auto srcTransform = CTransformation<CDomain>::getTransformation(transType, transId) ;
2066              transformation->inheritFrom(srcTransform) ;
2067              CGrid* tmpGridDst=CGrid::create(); // destination Grid
2068              tmpGridDst->addDomain(dstDomain->getId()) ;
2069
2070              algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 
2071                                                       posInGrid,posInGrid,posInGrid,
2072                                                       posInGrid,posInGrid,posInGrid );
2073
2074
2075              dstDomain->setTransformationAlgorithm(algo) ;
2076              dstDomain->setTransformationPaths(transformationPath) ;
2077            }
2078            algo=dstDomain->getTransformationAlgorithm() ;
2079            isGenerate = algo->isGenerateTransformation() ;
2080            transformationPath.removeNextTransform() ;
2081            dstElementId=transformationPath.getNextElementId() ;
2082            srcElementId=transformationPath.getNextElementSrcId() ;
2083            transType = transformationPath.getNextTransformationType() ;
2084            transId = transformationPath.getNextTransformationId() ;
2085            lastDstDomain=dstDomain ;
2086            dstDomain->setTransformationPaths(transformationPath) ;
2087          } while(transformationPath.hasTransform() && isGenerate) ;
2088
2089          if (isNewGrid) newGrid->addDomain(dstDomain->getId()) ;
2090          algo = dstDomain->getTransformationAlgorithm() ;
2091        }
2092        else if (dstElementType==EElement::AXIS)
2093        {
2094          CAxis* dstAxis ;
2095          CAxis* lastDstAxis ;
2096          bool isGenerate=false ;
2097
2098          do 
2099          {
2100            if (CAxis::has(dstElementId)) 
2101            {
2102              dstAxis = CAxis::get(dstElementId) ;
2103              info(100)<<"Retrive existing axis : "<<dstElementId<<endl ;
2104            }
2105            else
2106            {
2107              dstAxis = CAxis::create() ;
2108              dstAxis->createAlias(dstElementId) ;
2109              info(100)<<"Create new axis : "<<dstAxis->getId()<<" with alias : "<<dstElementId<<endl ;
2110             
2111              if (isGenerate) 
2112              {
2113                dstAxis->duplicateAttributes(lastDstAxis) ;
2114                dstAxis->setTemplateId(lastDstAxis) ;
2115              }
2116              else if (srcElementId=="" && srcElement.type==TYPE_AXIS) 
2117              { 
2118                dstAxis->duplicateAttributes(srcElement.axis) ; // make a copy
2119                dstAxis->setTemplateId(srcElement.axis) ;
2120              }
2121              else 
2122              {
2123                dstAxis->duplicateAttributes(dstElement.axis) ; // make a copy$
2124                dstAxis->setTemplateId(dstElement.axis) ;
2125              }
2126              CTransformation<CAxis>* transformation = CTransformation<CAxis>::createTransformation(transType,"") ;
2127              auto srcTransform = CTransformation<CAxis>::getTransformation(transType, transId) ;
2128              transformation->inheritFrom(srcTransform) ;
2129              tmpGridDst->addAxis(dstAxis->getId()) ;
2130
2131              algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 
2132                                                      posInGrid,posInGrid,posInGrid,
2133                                                      posInGrid,posInGrid,posInGrid );
2134
2135              dstAxis->setTransformationAlgorithm(algo) ;
2136              dstAxis->setTransformationPaths(transformationPath) ;
2137            }
2138           
2139            algo=dstAxis->getTransformationAlgorithm() ;
2140            isGenerate = algo->isGenerateTransformation() ;
2141            transformationPath.removeNextTransform() ;
2142            dstElementId=transformationPath.getNextElementId() ;
2143            srcElementId=transformationPath.getNextElementSrcId() ;
2144            transType = transformationPath.getNextTransformationType() ;
2145            transId = transformationPath.getNextTransformationId() ;
2146            lastDstAxis=dstAxis ;
2147            dstAxis->setTransformationPaths(transformationPath) ;
2148          } while(transformationPath.hasTransform() && isGenerate) ;
2149           
2150          if (isNewGrid) newGrid->addAxis(dstAxis->getId()) ;
2151          algo = dstAxis->getTransformationAlgorithm() ;
2152        }
2153        else if (dstElementType==EElement::SCALAR)
2154        {
2155          CScalar* dstScalar ;
2156          CScalar* lastDstScalar ;
2157          bool isGenerate=false ;
2158
2159          do 
2160          {
2161            if (CScalar::has(dstElementId)) 
2162            {
2163              dstScalar = CScalar::get(dstElementId) ;
2164              info(100)<<"Retrive existing scalar : "<<dstElementId<<endl ;
2165            }
2166            else
2167            {
2168              dstScalar = CScalar::create() ;
2169              dstScalar->createAlias(dstElementId) ;
2170              info(100)<<"Create new scalar : "<<dstScalar->getId()<<" with alias : "<<dstElementId<<endl ;
2171             
2172              if (isGenerate) 
2173              {
2174                dstScalar->duplicateAttributes(lastDstScalar) ;
2175                dstScalar->setTemplateId(lastDstScalar) ;
2176              }
2177              else if (srcElementId=="" && srcElement.type==TYPE_SCALAR)
2178              {
2179                dstScalar->duplicateAttributes(srcElement.scalar) ; // make a copy
2180                dstScalar->setTemplateId(srcElement.scalar) ;
2181              }
2182              else 
2183              {
2184                dstScalar->duplicateAttributes(dstElement.scalar) ; // make a copy
2185                dstScalar->setTemplateId(dstElement.scalar) ;
2186              }
2187              CTransformation<CScalar>* transformation = CTransformation<CScalar>::createTransformation(transType,"") ;
2188              auto srcTransform = CTransformation<CScalar>::getTransformation(transType, transId) ;
2189              transformation->inheritFrom(srcTransform) ;
2190              tmpGridDst->addScalar(dstScalar->getId()) ;
2191
2192              algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 
2193                                                       posInGrid,posInGrid,posInGrid,
2194                                                       posInGrid,posInGrid,posInGrid );
2195             
2196              dstScalar->setTransformationAlgorithm(algo) ;
2197              dstScalar->setTransformationPaths(transformationPath) ;
2198            }
2199            algo=dstScalar->getTransformationAlgorithm() ;
2200            isGenerate = algo->isGenerateTransformation() ;
2201            transformationPath.removeNextTransform() ;
2202            dstElementId=transformationPath.getNextElementId() ;
2203            srcElementId=transformationPath.getNextElementSrcId() ;
2204            transType = transformationPath.getNextTransformationType() ;
2205            transId = transformationPath.getNextTransformationId() ;
2206            lastDstScalar=dstScalar ;
2207            dstScalar->setTransformationPaths(transformationPath) ;
2208          } while(transformationPath.hasTransform() && isGenerate) ;
2209
2210          if (isNewGrid) newGrid->addScalar(dstScalar->getId()) ;
2211          algo = dstScalar->getTransformationAlgorithm() ;         
2212        }
2213        // here create a new spatial filter with algo
2214       
2215        hadTransform=true ;
2216        hasTransform=false ; 
2217      }
2218      else
2219      {
2220        string srcElementId=transformationPath.getNextElementSrcId() ;
2221
2222        if (srcElement.type==TYPE_DOMAIN)     
2223        {
2224          CDomain* domain ;
2225          if (srcElementId=="") srcElementId=srcElement.domain->getId() ; 
2226          if (!CDomain::has(srcElementId)) 
2227          {
2228            domain=srcElement.domain ;
2229            domain->createAlias(srcElementId) ;
2230          }
2231          else domain = CDomain::get(srcElementId) ;
2232          domain->checkAttributes() ;
2233         
2234          if (isNewGrid) newGrid->addDomain(srcElementId) ;
2235        }
2236        else if (srcElement.type==TYPE_AXIS)
2237        {   
2238          CAxis* axis ;
2239          if (srcElementId=="") srcElementId=srcElement.axis->getId() ; 
2240          if (!CAxis::has(srcElementId)) 
2241          {
2242            axis=srcElement.axis ;
2243            axis->createAlias(srcElementId) ;
2244          }
2245          else axis = CAxis::get(srcElementId) ;
2246          axis->checkAttributes() ;
2247         
2248          if (isNewGrid) newGrid->addAxis(srcElementId) ;
2249        }
2250        else if (srcElement.type==TYPE_SCALAR)
2251        {
2252          CScalar* scalar ;
2253          if (srcElementId=="") srcElementId=srcElement.scalar->getId() ; 
2254          if (!CScalar::has(srcElementId)) 
2255          {
2256            scalar=srcElement.scalar ;
2257            scalar->createAlias(srcElementId) ;
2258          }
2259          else scalar = CScalar::get(srcElementId) ;
2260          scalar->checkAttributes() ;
2261         
2262          if (isNewGrid) newGrid->addScalar(srcElementId) ;
2263        }
2264      }
2265     
2266      if (transformationPath.hasTransform() && hadTransform) hasRemainTransform=true ;
2267    } 
2268   
2269
2270    if (hadTransform)
2271    {
2272     
2273      if (!isSource)
2274      {
2275        shared_ptr<CGridAlgorithm> gridAlgorithm  ;
2276        if (isNewGrid)
2277        { 
2278          gridAlgorithm = algo->createGridAlgorithm(gridSrc, newGrid, pos) ;
2279          newGrid->setGridAlgorithm(gridAlgorithm);
2280        }
2281        else gridAlgorithm = newGrid->getGridAlgorithm() ;
2282
2283        shared_ptr<CTransformFilter> transformFilter = shared_ptr<CTransformFilter>(gridAlgorithm->createTransformFilter(gc, detectMissingValues, defaultValue)) ;
2284        outputFilter->connectOutput(transformFilter,0) ;
2285        if(graphEnabled)
2286        {
2287          transformFilter->graphEnabled=true;
2288          transformFilter->graphPackage = new CGraphPackage;
2289          transformFilter->graphPackage->inFields.push_back(field);
2290          transformFilter->graphPackage->show = !transformationGoing;
2291        }
2292       
2293        vector<string> auxFieldId = algo->getAuxFieldId() ; // better to do that at transformation not algo ??
2294        int i=1; 
2295        for (auto& it : auxFieldId)
2296        {
2297          CField* auxField = CField::get(it) ;
2298          auxField->buildWorkflowGraph(gc) ;
2299          auxField->getInstantDataFilter()->connectOutput(transformFilter,i) ;
2300          i++ ;
2301        }
2302        outputFilter = transformFilter ;
2303      }
2304
2305      if (hasRemainTransform)
2306      {
2307        transformationGoing = true;
2308        gridSrc=newGrid ;
2309        CField *field_bis = field;
2310        pair<shared_ptr<CFilter>, shared_ptr<CFilter> > filters = this->buildTransformationGraph(gc, isSource, gridSrc, detectMissingValues, defaultValue, newGrid, graphEnabled, field_bis) ;
2311        outputFilter->connectOutput(filters.first,0) ;
2312        outputFilter=filters.second ;
2313      }
2314      transformationGoing = false;
2315    }
2316     
2317    return {inputFilter,outputFilter} ;
2318  }
2319  CATCH_DUMP_ATTR
2320
2321
2322//****************************************************************
2323//****************************************************************
2324
2325//----------------------------------------------------------------
2326
2327  CGrid* CGrid::duplicateSentGrid(void)
2328  {
2329    CGrid* newGrid ;
2330    string sentGridId="sent__"+getId() ;
2331    if (has(sentGridId)) newGrid = get(sentGridId) ;
2332    else
2333    {
2334      newGrid = CGrid::create(sentGridId) ;
2335      for(auto element : elements_)
2336      {
2337        if (element.type==TYPE_DOMAIN)     
2338        {
2339          CDomain* domain = CDomain::create();
2340          domain->duplicateAttributes(element.domain) ;
2341          domain->setTemplateId(element.domain) ;
2342          domain->name = domain->getDomainOutputName() ;
2343          newGrid->addDomain(domain->getId()) ;
2344        }
2345        else if (element.type==TYPE_AXIS)     
2346        {
2347          CAxis* axis = CAxis::create();
2348          axis->duplicateAttributes(element.axis) ;
2349          axis->setTemplateId(element.axis) ;
2350          axis->name = axis->getAxisOutputName() ;
2351          newGrid->addAxis(axis->getId()) ;
2352        }
2353        else if (element.type==TYPE_SCALAR)     
2354        {
2355          CScalar* scalar = CScalar::create();
2356          scalar->duplicateAttributes(element.scalar) ;
2357          scalar->setTemplateId(element.scalar) ;
2358          scalar->name = scalar->getScalarOutputName() ;
2359          newGrid->addScalar(scalar->getId()) ;
2360        }
2361      }
2362      newGrid->checkElementsAttributes() ;
2363    }
2364    return newGrid ;
2365  }
2366
2367
2368  void CGrid::setContextClient(CContextClient* contextClient)
2369  TRY
2370  {
2371    if (clientsSet.find(contextClient)==clientsSet.end())
2372    {
2373      clients.push_back(contextClient) ;
2374      clientsSet.insert(contextClient);
2375    }
2376    for (auto domain : getDomains()) domain->setContextClient(contextClient);
2377    for (auto axis : getAxis()) axis->setContextClient(contextClient);
2378    for (auto scalar : getScalars()) scalar->setContextClient(contextClient);
2379   
2380  }
2381  CATCH_DUMP_ATTR
2382
2383 
2384  void CGrid::computeGridLocalElements()
2385  {
2386    std::vector<CDomain*> domainList = this->getDomains();
2387    std::vector<CAxis*> axisList = this->getAxis();
2388    std::vector<CScalar*> scalarList = this->getScalars();
2389    auto domain=domainList.begin() ;
2390    auto axis=axisList.begin() ;
2391    auto scalar=scalarList.begin() ;
2392    vector<shared_ptr<CLocalElement>> elements;
2393    for(auto order : order_)
2394    {
2395      if (order==2) 
2396      {
2397        elements.push_back((*domain)->getLocalElement());
2398        domain++ ;
2399      }
2400      else if (order==1)
2401      {
2402        elements.push_back((*axis)->getLocalElement());
2403        axis++ ;
2404      }
2405      else if (order==0)
2406      { 
2407        elements.push_back((*scalar)->getLocalElement());
2408        scalar++ ;
2409      }
2410    }
2411    if (hasMask()) 
2412    {
2413      vector<bool> mask(getMask().getVector()) ;
2414      gridLocalElements_ = make_shared<CGridLocalElements>(elements, mask) ; 
2415    }
2416    else gridLocalElements_ = make_shared<CGridLocalElements>(elements) ; 
2417  }
2418
2419  void CGrid::computeModelToWorkflowConnector(void)
2420  {
2421    modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW,true) ;
2422  }
2423
2424  void CGrid::computeWorkflowToFullConnector(void)
2425  {
2426    workflowToFullConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::FULL) ;
2427  }
2428
2429  void CGrid::computeWorkflowToModelConnector(void)
2430  {
2431    workflowToModelConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::MODEL,true) ;
2432  }
2433
2434  void CGrid::computeFullToWorkflowConnector(void)
2435  {
2436    fullToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::FULL,CElementView::WORKFLOW) ;
2437  }
2438
2439  void CGrid::computeServerFromClientConnector(void)
2440  {
2441    vector<shared_ptr<CGathererConnector>> connectors ;
2442    for(auto& element : getElements())
2443    {
2444      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
2445      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
2446      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
2447    }
2448    serverFromClientConnector_ = make_shared<CGridGathererConnector>(connectors) ;
2449  }
2450
2451  void CGrid::computeServerToClientConnector(void)
2452  {
2453    vector<shared_ptr<CScattererConnector>> connectors ;
2454    for(auto& element : getElements())
2455    {
2456      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerToClientConnector()) ;
2457      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerToClientConnector()) ; 
2458      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerToClientConnector()) ; 
2459    }
2460    serverToClientConnector_ = make_shared<CGridScattererConnector>(connectors) ;
2461  }
2462
2463  void CGrid::computeClientFromClientConnector(void)
2464  {
2465    vector<shared_ptr<CGathererConnector>> connectors ;
2466    for(auto& element : getElements())
2467    {
2468      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
2469      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
2470      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
2471    }
2472    clientFromClientConnector_ = make_shared<CGridGathererConnector>(connectors) ;
2473  }
2474
2475 
2476} // namespace xios
Note: See TracBrowser for help on using the repository browser.