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

Last change on this file since 2343 was 2343, checked in by ymipsl, 2 years ago
  • Implement new infrastructure for transfert protocol.
  • new purelly one sided protocol is now available, the previous protocol (legacy, mix send/recv and one sided) is still available. Other specific protocol could be implemented more easilly in future.
  • switch can be operate with "transport_protocol" variable in XIOS context :

ex:
<variable id="transport_protocol" type="string">one_sided</variable>

Available protocols are : one_sided, legacy or default. The default protocol is "legacy".

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: 83.9 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)
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) ;
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, fieldId) ;
1469  }
1470
1471
1472  void CGrid::distributeGridToServer(CContextClient* client, 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->computeConnector(true) ;
1523   
1524    auto gridRemoteConnectorIn = make_shared<CGridClientServerRemoteConnector>(localViews, workflowView, remoteViews, context->getIntraComm(), client->getRemoteSize()) ;
1525    gridRemoteConnectorIn->computeConnector(false) ;
1526
1527   
1528    vector<shared_ptr<CScattererConnector>> scattererConnectors ;
1529    shared_ptr<CScattererConnector> scattererConnector;
1530    for(int i=0 ; i<elements.size() ; i++)
1531    {
1532      if (elements[i].type==TYPE_DOMAIN) 
1533      { 
1534        CDomain* domain = (CDomain*) elements[i].ptr ;
1535        if (isCoupling) domain->distributeToServer(client, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i),
1536                                                   scattererConnector,  domain->getCouplingAlias(fieldId,i)) ;
1537        else 
1538        {
1539          sendAddDomain(domain->getId(),client) ;
1540          domain->distributeToServer(client, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i), scattererConnector) ;
1541        }
1542        scattererConnectors.push_back(scattererConnector) ;
1543      }
1544      else if (elements[i].type==TYPE_AXIS)
1545      {
1546        CAxis* axis = (CAxis*) elements[i].ptr ;
1547        if (isCoupling) axis->distributeToServer(client, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i),
1548                                                 scattererConnector,  axis->getCouplingAlias(fieldId,i)) ;
1549        else 
1550        {
1551          sendAddAxis(axis->getId(),client) ;
1552          axis->distributeToServer(client, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i), scattererConnector) ;
1553        }
1554        scattererConnectors.push_back(scattererConnector) ;
1555      }
1556      else if (elements[i].type==TYPE_SCALAR)
1557      {
1558        CScalar* scalar = (CScalar*) elements[i].ptr ;
1559        if (isCoupling) scalar->distributeToServer(client, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i),
1560                                                   scattererConnector,  scalar->getCouplingAlias(fieldId,i)) ;
1561        else 
1562        {
1563          sendAddScalar(scalar->getId(),client) ;
1564          scalar->distributeToServer(client, gridRemoteConnector->getDistributedGlobalIndex(i), gridRemoteConnectorIn->getDistributedGlobalIndex(i), scattererConnector) ;
1565        }
1566        scattererConnectors.push_back(scattererConnector) ;
1567      }
1568    }
1569
1570    auto gridScattererConnector = make_shared<CGridScattererConnector>(scattererConnectors) ;
1571    shared_ptr<CGridLocalConnector> workflowToFull = getGridLocalElements()->getConnector(CElementView::WORKFLOW, CElementView::FULL) ;
1572    CArray<bool,1> maskIn(workflowToFull->getSrcSize()) ;
1573    CArray<bool,1> maskOut(workflowToFull->getDstSize()) ;
1574    maskIn = true ;
1575    workflowToFull->transfer(maskIn,maskOut,false) ;
1576
1577    CEventClient event(getType(), EVENT_ID_SEND_MASK);
1578    CMessage message ;
1579    if (isCoupling) message<<getCouplingAlias(fieldId) ;
1580    else message<<getId() ; 
1581    gridScattererConnector->transfer(maskOut, client, event, message) ;
1582   
1583    vector<shared_ptr<CScattererConnector>> clientToServerConnectors ;
1584    vector<shared_ptr<CGathererConnector>>  clientFromServerConnectors ;
1585    for(auto& element : elements)
1586    {
1587      if (element.type==TYPE_DOMAIN) 
1588      { 
1589         clientToServerConnectors.push_back(element.domain->getClientToServerConnector(client)) ;
1590         clientFromServerConnectors.push_back(element.domain->getClientFromServerConnector(client)) ;
1591      }
1592      else if (element.type==TYPE_AXIS)
1593      {
1594        clientToServerConnectors.push_back(element.axis->getClientToServerConnector(client)) ;
1595        clientFromServerConnectors.push_back(element.axis->getClientFromServerConnector(client)) ;
1596
1597      }
1598      else if (element.type==TYPE_SCALAR)
1599      {
1600        clientToServerConnectors.push_back(element.scalar->getClientToServerConnector(client)) ;
1601        clientFromServerConnectors.push_back(element.scalar->getClientFromServerConnector(client)) ;
1602      }
1603    }
1604   
1605    // compute the grid clientToServerConnector to send flux from client to servers
1606    clientToServerConnector_[client] = make_shared<CGridScattererConnector>(clientToServerConnectors) ;
1607    clientFromServerConnector_[client] = make_shared<CGridGathererConnector>(clientFromServerConnectors) ;
1608
1609  }
1610
1611
1612  void CGrid::recvMask(CEventServer& event)
1613  {
1614    string gridId;
1615    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> gridId  ;
1616    get(gridId)->receiveMask(event);
1617  }
1618 
1619  void CGrid::receiveMask(CEventServer& event)
1620  {
1621    vector<shared_ptr<CGathererConnector>> gathererConnectors ;
1622    vector<shared_ptr<CLocalView>> fullViews ;
1623
1624    for(auto& element : getElements())
1625    {
1626      if (element.type==TYPE_DOMAIN) 
1627      {
1628        gathererConnectors.push_back(element.domain->getGathererConnector());
1629        fullViews.push_back(element.domain->getLocalElement()->getView(CElementView::FULL));
1630       
1631      }
1632      else if (element.type==TYPE_AXIS)
1633      {
1634       gathererConnectors.push_back(element.axis->getGathererConnector());
1635       fullViews.push_back(element.axis->getLocalElement()->getView(CElementView::FULL));
1636      }
1637      else if (element.type==TYPE_SCALAR) 
1638      {
1639        gathererConnectors.push_back(element.scalar->getGathererConnector());
1640        fullViews.push_back(element.scalar->getLocalElement()->getView(CElementView::FULL));
1641      }
1642    }
1643    auto gridGathererConnector = make_shared<CGridGathererConnector>(gathererConnectors) ;
1644    auto gridMaskConnector = make_shared<CGridMaskConnector>(fullViews) ;
1645
1646    CArray<bool,1> maskOut ;
1647    gridGathererConnector->transfer_or(event,maskOut) ;
1648    gridMaskConnector->computeConnector(maskOut) ;
1649
1650    CContextClient* client = event.getContextServer()->getAssociatedClient() ;
1651    int i=0 ;
1652    for(auto& element : getElements())
1653    {
1654      if (element.type==TYPE_DOMAIN) element.domain->setServerMask(gridMaskConnector->getElementMask(i),client);
1655      else if (element.type==TYPE_AXIS) element.axis->setServerMask(gridMaskConnector->getElementMask(i),client);
1656      else if (element.type==TYPE_SCALAR) element.scalar->setServerMask(gridMaskConnector->getElementMask(i),client);
1657      i++ ;
1658    }
1659  }
1660
1661  string CGrid::getCouplingAlias(const string& fieldId)
1662  {
1663    return "_grid_of_"+fieldId;
1664  }
1665
1666  void CGrid::makeAliasForCoupling(const string& fieldId)
1667  {
1668    string gridId=getCouplingAlias(fieldId) ;
1669    createAlias(gridId) ;
1670
1671    auto& elements = getElements() ;
1672    for(int i=0 ; i<elements.size() ; i++)
1673    {
1674      if (elements[i].type==TYPE_DOMAIN) elements[i].domain->makeAliasForCoupling(fieldId, i);
1675      else if (elements[i].type==TYPE_AXIS) elements[i].axis->makeAliasForCoupling(fieldId, i);
1676      else if (elements[i].type==TYPE_SCALAR) elements[i].scalar->makeAliasForCoupling(fieldId, i);
1677    }
1678  }
1679
1680   /*!
1681   \brief Send a message to create a domain on server side
1682   \param[in] id String identity of domain that will be created on server
1683   */
1684   void CGrid::sendAddDomain(const string& id, CContextClient* contextClient)
1685   TRY
1686  {
1687      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN, contextClient);
1688   }
1689   CATCH_DUMP_ATTR
1690
1691   /*!
1692   \brief Send a message to create an axis on server side
1693   \param[in] id String identity of axis that will be created on server
1694   */
1695   void CGrid::sendAddAxis(const string& id, CContextClient* contextClient)
1696   TRY
1697   {
1698      sendAddItem(id, (int)EVENT_ID_ADD_AXIS, contextClient);
1699   }
1700   CATCH_DUMP_ATTR
1701
1702   /*!
1703   \brief Send a message to create a scalar on server side
1704   \param[in] id String identity of scalar that will be created on server
1705   */
1706   void CGrid::sendAddScalar(const string& id, CContextClient* contextClient)
1707   TRY
1708   {
1709      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR, contextClient);
1710   }
1711   CATCH_DUMP_ATTR
1712
1713   /*!
1714   \brief Receive a message annoucing the creation of a domain on server side
1715   \param[in] event Received event
1716   */
1717   void CGrid::recvAddDomain(CEventServer& event)
1718   TRY
1719   {
1720
1721      CBufferIn* buffer = event.subEvents.begin()->buffer;
1722      string id;
1723      *buffer >> id;
1724      get(id)->recvAddDomain(*buffer);
1725   }
1726   CATCH
1727
1728   /*!
1729   \brief Receive a message annoucing the creation of a domain on server side
1730   \param[in] buffer Buffer containing message
1731   */
1732   void CGrid::recvAddDomain(CBufferIn& buffer)
1733   TRY
1734   {
1735      string id;
1736      buffer >> id;
1737      addDomain(id);
1738   }
1739   CATCH_DUMP_ATTR
1740
1741   /*!
1742   \brief Receive a message annoucing the creation of an axis on server side
1743   \param[in] event Received event
1744   */
1745   void CGrid::recvAddAxis(CEventServer& event)
1746   TRY
1747   {
1748
1749      CBufferIn* buffer = event.subEvents.begin()->buffer;
1750      string id;
1751      *buffer >> id;
1752      get(id)->recvAddAxis(*buffer);
1753   }
1754   CATCH
1755
1756   /*!
1757   \brief Receive a message annoucing the creation of an axis on server side
1758   \param[in] buffer Buffer containing message
1759   */
1760   void CGrid::recvAddAxis(CBufferIn& buffer)
1761   TRY
1762   {
1763      string id;
1764      buffer >> id;
1765      addAxis(id);
1766   }
1767   CATCH_DUMP_ATTR
1768
1769   /*!
1770   \brief Receive a message annoucing the creation of an scalar on server side
1771   \param[in] event Received event
1772   */
1773   void CGrid::recvAddScalar(CEventServer& event)
1774   TRY
1775   {
1776
1777      CBufferIn* buffer = event.subEvents.begin()->buffer;
1778      string id;
1779      *buffer >> id;
1780      get(id)->recvAddScalar(*buffer);
1781   }
1782   CATCH
1783
1784   /*!
1785   \brief Receive a message annoucing the creation of an scalar on server side
1786   \param[in] buffer Buffer containing message
1787   */
1788   void CGrid::recvAddScalar(CBufferIn& buffer)
1789   TRY
1790   {
1791      string id;
1792      buffer >> id;
1793      addScalar(id);
1794   }
1795   CATCH_DUMP_ATTR
1796
1797  /*!
1798  \brief Check if all elements of the grid are complete
1799  Before make any grid processing, we must be sure that all grid information elements have
1800  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1801  other context (coupling)
1802  */
1803  bool CGrid::isCompleted(void)
1804  {
1805    setDomainList();
1806    for (auto domainId : domList_) if (!CDomain::get(domainId)->isCompleted()) return false ;
1807    setAxisList() ;
1808    for (auto axisId : axisList_) if (!CAxis::get(axisId)->isCompleted()) return false ;
1809    setScalarList() ;
1810    for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->isCompleted()) return false ;
1811    return true ;
1812  }
1813
1814  /*!
1815  \brief impose that all elements of the grid are complete
1816  Before make any grid processing, we must be sure that all grid information elements have
1817  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1818  other context (coupling)
1819  */
1820  void CGrid::setCompleted(void)
1821  {
1822    setDomainList();
1823    for (auto domainId : domList_) CDomain::get(domainId)->setCompleted() ;
1824    setAxisList() ;
1825    for (auto axisId : axisList_) CAxis::get(axisId)->setCompleted() ;
1826    setScalarList() ;
1827    for (auto scalarId : scalarList_) CScalar::get(scalarId)->setCompleted() ;
1828  }
1829
1830/*!
1831  \brief impose that all elements of the grid are incomplete
1832  Before make any grid processing, we must be sure that all grid information elements have
1833  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1834  other context (coupling)
1835  */
1836  void CGrid::unsetCompleted(void)
1837  {
1838    setDomainList();
1839    for (auto domainId : domList_) CDomain::get(domainId)->unsetCompleted() ;
1840    setAxisList() ;
1841    for (auto axisId : axisList_) CAxis::get(axisId)->unsetCompleted() ;
1842    setScalarList() ;
1843    for (auto scalarId : scalarList_) CScalar::get(scalarId)->unsetCompleted() ;
1844  }
1845
1846  /*!
1847  \brief Solve domain and axis references
1848  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
1849  all attributes from their parents, they should be processed with this function
1850  \param[in] apply inherit all attributes of parents (true)
1851  */
1852  void CGrid::solveElementsRefInheritance(bool apply)
1853  TRY
1854  {
1855    setDomainList();
1856    for (auto domainId : domList_)
1857    {
1858      CDomain* pDom = CDomain::get(domainId);
1859      pDom->solveRefInheritance(apply);
1860      if (apply) pDom->solveInheritanceTransformation();
1861    }
1862
1863    setAxisList();
1864    for (auto axisId : axisList_)
1865    {
1866      CAxis* pAxis = CAxis::get(axisId);
1867      pAxis->solveRefInheritance(apply);
1868      if (apply) pAxis->solveInheritanceTransformation();
1869    }
1870
1871    setScalarList();
1872    for (auto scalarId : scalarList_)
1873    {
1874      CScalar* pScalar = CScalar::get(scalarId);
1875      pScalar->solveRefInheritance(apply);
1876      if (apply) pScalar->solveInheritanceTransformation();
1877    }
1878  }
1879  CATCH_DUMP_ATTR
1880
1881  bool CGrid::activateFieldWorkflow(CGarbageCollector& gc)
1882  TRY
1883  {
1884    setDomainList();
1885    for (auto domainId : domList_)
1886    {
1887      CDomain* pDom = CDomain::get(domainId);
1888      bool ret = pDom->activateFieldWorkflow(gc);
1889      if (!ret) return false ;
1890    }
1891
1892    setAxisList();
1893    for (auto axisId : axisList_)
1894    {
1895      CAxis* pAxis = CAxis::get(axisId);
1896      bool ret = pAxis->activateFieldWorkflow(gc);
1897      if (!ret) return false ;
1898    }
1899
1900    setScalarList();
1901    for (auto scalarId : scalarList_)
1902    {
1903      CScalar* pScalar = CScalar::get(scalarId);
1904      bool ret = pScalar->activateFieldWorkflow(gc);
1905      if (!ret) return false ;
1906    }
1907    return true ;
1908  }
1909  CATCH_DUMP_ATTR
1910
1911 /*!
1912  \brief check attributes of all elements of the grid
1913  */
1914  void CGrid::checkElementsAttributes(void)
1915  TRY
1916  {
1917    setDomainList();
1918    for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes();
1919
1920    setAxisList();
1921    for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes();
1922   
1923    setScalarList();
1924    for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes();
1925  }
1926  CATCH_DUMP_ATTR
1927
1928
1929
1930//**********************************************************
1931//**************   New transformation method  **************
1932//**********************************************************
1933
1934  std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > 
1935  CGrid::buildTransformationGraph(CGarbageCollector& gc, bool isSource, CGrid* gridSrc, double detectMissingValues, double defaultValue, CGrid*& newGrid, bool graphEnabled, CField* field)
1936  TRY
1937  {
1938    static bool transformationGoing = false;
1939    registerAlgorithmTransformation() ; // needed to enable self-registration of the transformations
1940                                        // big mystery why it doesn't work witout that...
1941                                        // problem with the linker ??
1942
1943    std::shared_ptr<CFilter> inputFilter = std::shared_ptr<CPassThroughFilter>(new CPassThroughFilter(gc));
1944    std::shared_ptr<CFilter> outputFilter = inputFilter ;
1945
1946
1947    string newId ;
1948    if (gridSrc!=nullptr) newId = gridSrc->getId() + " --> " + this->getId()  ;
1949    else newId = " --> " + this->getId()  ;
1950    bool isNewGrid ;
1951    if (CGrid::has(newId))
1952    {
1953      cout<<"Retrive existing grid : "<<newId<<endl ;
1954      newGrid = CGrid::get(newId);
1955      isNewGrid = false ;
1956    }
1957    else 
1958    {
1959      cout<<"Create new grid : "<<newId<<endl ;
1960      newGrid = CGrid::create(newId) ;
1961      isNewGrid = true ;
1962    }
1963
1964    bool hadTransform=false ;
1965    bool hasTransform=false ;
1966    bool hasRemainTransform=false ;
1967    shared_ptr<CGenericAlgorithmTransformation> algo ;
1968    int pos ;
1969
1970    for(int i=0 ; i<elements_.size(); i++)
1971    {
1972      CTransformationPaths transformationPath ;
1973      auto dstElement = elements_[i] ;
1974
1975      if (dstElement.type==TYPE_DOMAIN)      transformationPath = dstElement.domain->getTransformationPaths() ;
1976      else if (dstElement.type==TYPE_AXIS)   transformationPath = dstElement.axis->getTransformationPaths() ;
1977      else if (dstElement.type==TYPE_SCALAR) transformationPath = dstElement.scalar->getTransformationPaths() ;
1978
1979      SElement srcElement  ;
1980      if (gridSrc==nullptr) srcElement = this->elements_[i] ;
1981      else srcElement = gridSrc->elements_[i] ;
1982
1983      if (gridSrc==nullptr) transformationPath.mergePaths() ;
1984      else
1985      { 
1986        if (srcElement.type==TYPE_DOMAIN)      transformationPath.mergePaths(srcElement.domain->getTransformationPaths()) ;
1987        else if (srcElement.type==TYPE_AXIS)   transformationPath.mergePaths(srcElement.axis->getTransformationPaths()) ;
1988        else if (srcElement.type==TYPE_SCALAR) transformationPath.mergePaths(srcElement.scalar->getTransformationPaths()) ;
1989      }
1990
1991      hasTransform=transformationPath.hasTransform()  ;
1992     
1993      if (hasTransform && !hadTransform)
1994      {
1995        pos=i ;
1996        EElement dstElementType=transformationPath.getNextElementType() ;
1997        string dstElementId=transformationPath.getNextElementId() ;
1998        string srcElementId=transformationPath.getNextElementSrcId() ;
1999        auto transType = transformationPath.getNextTransformationType() ;
2000        auto transId = transformationPath.getNextTransformationId() ;
2001
2002        CGrid* tmpGridSrc=CGrid::create(); // source grid
2003        if (srcElement.type==TYPE_DOMAIN)      tmpGridSrc->addDomain(srcElement.domain->getId()) ;
2004        else if (srcElement.type==TYPE_AXIS)   tmpGridSrc->addAxis(srcElement.axis->getId()) ;
2005        else if (srcElement.type==TYPE_SCALAR) tmpGridSrc->addScalar(srcElement.scalar->getId()) ;
2006        // WARNING -> suppress checkElement attribute ? What append ?
2007        // tmpGridSrc->checkElementsAttributes() ;
2008        CGrid* tmpGridDst=CGrid::create(); // destination Grid
2009        map<int,int> posInGrid={{0,0}} ;
2010               
2011        cout<<"--> New transform from "<<srcElementId<<" to "<<dstElementId<<endl ;
2012        if (dstElementType==EElement::DOMAIN)
2013        {
2014          CDomain* dstDomain ;
2015          CDomain* lastDstDomain ;
2016          bool isGenerate=false ;
2017   
2018          do 
2019          {
2020
2021            if (CDomain::has(dstElementId)) 
2022            {
2023              dstDomain = CDomain::get(dstElementId) ;
2024              cout<<"Retrive existing domain : "<<dstElementId<<endl ;
2025            }
2026            else
2027            {
2028              dstDomain = CDomain::create() ;
2029              dstDomain->createAlias(dstElementId) ;
2030              cout<<"Create new domain : "<<dstDomain->getId()<<" with alias : "<<dstElementId<<endl ;
2031
2032              if (isGenerate) 
2033              {
2034                dstDomain->duplicateAttributes(lastDstDomain) ;
2035                dstDomain->setTemplateId(lastDstDomain) ;
2036              }
2037              else if (srcElementId=="" && srcElement.type==TYPE_DOMAIN) 
2038              {
2039                dstDomain->duplicateAttributes(srcElement.domain) ; // make a copy
2040                dstDomain->setTemplateId(srcElement.domain) ;
2041              }
2042              else 
2043              {
2044                dstDomain->duplicateAttributes(dstElement.domain) ; // make a copy
2045                dstDomain->setTemplateId(dstElement.domain) ;
2046              }
2047              CTransformation<CDomain>* transformation = CTransformation<CDomain>::createTransformation(transType,"") ;
2048              auto srcTransform = CTransformation<CDomain>::getTransformation(transType, transId) ;
2049              transformation->inheritFrom(srcTransform) ;
2050              CGrid* tmpGridDst=CGrid::create(); // destination Grid
2051              tmpGridDst->addDomain(dstDomain->getId()) ;
2052
2053              algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 
2054                                                       posInGrid,posInGrid,posInGrid,
2055                                                       posInGrid,posInGrid,posInGrid );
2056
2057
2058              dstDomain->setTransformationAlgorithm(algo) ;
2059              dstDomain->setTransformationPaths(transformationPath) ;
2060            }
2061            algo=dstDomain->getTransformationAlgorithm() ;
2062            isGenerate = algo->isGenerateTransformation() ;
2063            transformationPath.removeNextTransform() ;
2064            dstElementId=transformationPath.getNextElementId() ;
2065            srcElementId=transformationPath.getNextElementSrcId() ;
2066            transType = transformationPath.getNextTransformationType() ;
2067            transId = transformationPath.getNextTransformationId() ;
2068            lastDstDomain=dstDomain ;
2069            dstDomain->setTransformationPaths(transformationPath) ;
2070          } while(transformationPath.hasTransform() && isGenerate) ;
2071
2072          if (isNewGrid) newGrid->addDomain(dstDomain->getId()) ;
2073          algo = dstDomain->getTransformationAlgorithm() ;
2074        }
2075        else if (dstElementType==EElement::AXIS)
2076        {
2077          CAxis* dstAxis ;
2078          CAxis* lastDstAxis ;
2079          bool isGenerate=false ;
2080
2081          do 
2082          {
2083            if (CAxis::has(dstElementId)) 
2084            {
2085              dstAxis = CAxis::get(dstElementId) ;
2086              cout<<"Retrive existing axis : "<<dstElementId<<endl ;
2087            }
2088            else
2089            {
2090              dstAxis = CAxis::create() ;
2091              dstAxis->createAlias(dstElementId) ;
2092              cout<<"Create new axis : "<<dstAxis->getId()<<" with alias : "<<dstElementId<<endl ;
2093             
2094              if (isGenerate) 
2095              {
2096                dstAxis->duplicateAttributes(lastDstAxis) ;
2097                dstAxis->setTemplateId(lastDstAxis) ;
2098              }
2099              else if (srcElementId=="" && srcElement.type==TYPE_AXIS) 
2100              { 
2101                dstAxis->duplicateAttributes(srcElement.axis) ; // make a copy
2102                dstAxis->setTemplateId(srcElement.axis) ;
2103              }
2104              else 
2105              {
2106                dstAxis->duplicateAttributes(dstElement.axis) ; // make a copy$
2107                dstAxis->setTemplateId(dstElement.axis) ;
2108              }
2109              CTransformation<CAxis>* transformation = CTransformation<CAxis>::createTransformation(transType,"") ;
2110              auto srcTransform = CTransformation<CAxis>::getTransformation(transType, transId) ;
2111              transformation->inheritFrom(srcTransform) ;
2112              tmpGridDst->addAxis(dstAxis->getId()) ;
2113
2114              algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 
2115                                                      posInGrid,posInGrid,posInGrid,
2116                                                      posInGrid,posInGrid,posInGrid );
2117
2118              dstAxis->setTransformationAlgorithm(algo) ;
2119              dstAxis->setTransformationPaths(transformationPath) ;
2120            }
2121           
2122            algo=dstAxis->getTransformationAlgorithm() ;
2123            isGenerate = algo->isGenerateTransformation() ;
2124            transformationPath.removeNextTransform() ;
2125            dstElementId=transformationPath.getNextElementId() ;
2126            srcElementId=transformationPath.getNextElementSrcId() ;
2127            transType = transformationPath.getNextTransformationType() ;
2128            transId = transformationPath.getNextTransformationId() ;
2129            lastDstAxis=dstAxis ;
2130            dstAxis->setTransformationPaths(transformationPath) ;
2131          } while(transformationPath.hasTransform() && isGenerate) ;
2132           
2133          if (isNewGrid) newGrid->addAxis(dstAxis->getId()) ;
2134          algo = dstAxis->getTransformationAlgorithm() ;
2135        }
2136        else if (dstElementType==EElement::SCALAR)
2137        {
2138          CScalar* dstScalar ;
2139          CScalar* lastDstScalar ;
2140          bool isGenerate=false ;
2141
2142          do 
2143          {
2144            if (CScalar::has(dstElementId)) 
2145            {
2146              dstScalar = CScalar::get(dstElementId) ;
2147              cout<<"Retrive existing scalar : "<<dstElementId<<endl ;
2148            }
2149            else
2150            {
2151              dstScalar = CScalar::create() ;
2152              dstScalar->createAlias(dstElementId) ;
2153              cout<<"Create new scalar : "<<dstScalar->getId()<<" with alias : "<<dstElementId<<endl ;
2154             
2155              if (isGenerate) 
2156              {
2157                dstScalar->duplicateAttributes(lastDstScalar) ;
2158                dstScalar->setTemplateId(lastDstScalar) ;
2159              }
2160              else if (srcElementId=="" && srcElement.type==TYPE_SCALAR)
2161              {
2162                dstScalar->duplicateAttributes(srcElement.scalar) ; // make a copy
2163                dstScalar->setTemplateId(srcElement.scalar) ;
2164              }
2165              else 
2166              {
2167                dstScalar->duplicateAttributes(dstElement.scalar) ; // make a copy
2168                dstScalar->setTemplateId(dstElement.scalar) ;
2169              }
2170              CTransformation<CScalar>* transformation = CTransformation<CScalar>::createTransformation(transType,"") ;
2171              auto srcTransform = CTransformation<CScalar>::getTransformation(transType, transId) ;
2172              transformation->inheritFrom(srcTransform) ;
2173              tmpGridDst->addScalar(dstScalar->getId()) ;
2174
2175              algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 
2176                                                       posInGrid,posInGrid,posInGrid,
2177                                                       posInGrid,posInGrid,posInGrid );
2178             
2179              dstScalar->setTransformationAlgorithm(algo) ;
2180              dstScalar->setTransformationPaths(transformationPath) ;
2181            }
2182            algo=dstScalar->getTransformationAlgorithm() ;
2183            isGenerate = algo->isGenerateTransformation() ;
2184            transformationPath.removeNextTransform() ;
2185            dstElementId=transformationPath.getNextElementId() ;
2186            srcElementId=transformationPath.getNextElementSrcId() ;
2187            transType = transformationPath.getNextTransformationType() ;
2188            transId = transformationPath.getNextTransformationId() ;
2189            lastDstScalar=dstScalar ;
2190            dstScalar->setTransformationPaths(transformationPath) ;
2191          } while(transformationPath.hasTransform() && isGenerate) ;
2192
2193          if (isNewGrid) newGrid->addScalar(dstScalar->getId()) ;
2194          algo = dstScalar->getTransformationAlgorithm() ;         
2195        }
2196        // here create a new spatial filter with algo
2197       
2198        hadTransform=true ;
2199        hasTransform=false ; 
2200      }
2201      else
2202      {
2203        string srcElementId=transformationPath.getNextElementSrcId() ;
2204
2205        if (srcElement.type==TYPE_DOMAIN)     
2206        {
2207          CDomain* domain ;
2208          if (srcElementId=="") srcElementId=srcElement.domain->getId() ; 
2209          if (!CDomain::has(srcElementId)) 
2210          {
2211            domain=srcElement.domain ;
2212            domain->createAlias(srcElementId) ;
2213          }
2214          else domain = CDomain::get(srcElementId) ;
2215          domain->checkAttributes() ;
2216         
2217          if (isNewGrid) newGrid->addDomain(srcElementId) ;
2218        }
2219        else if (srcElement.type==TYPE_AXIS)
2220        {   
2221          CAxis* axis ;
2222          if (srcElementId=="") srcElementId=srcElement.axis->getId() ; 
2223          if (!CAxis::has(srcElementId)) 
2224          {
2225            axis=srcElement.axis ;
2226            axis->createAlias(srcElementId) ;
2227          }
2228          else axis = CAxis::get(srcElementId) ;
2229          axis->checkAttributes() ;
2230         
2231          if (isNewGrid) newGrid->addAxis(srcElementId) ;
2232        }
2233        else if (srcElement.type==TYPE_SCALAR)
2234        {
2235          CScalar* scalar ;
2236          if (srcElementId=="") srcElementId=srcElement.scalar->getId() ; 
2237          if (!CScalar::has(srcElementId)) 
2238          {
2239            scalar=srcElement.scalar ;
2240            scalar->createAlias(srcElementId) ;
2241          }
2242          else scalar = CScalar::get(srcElementId) ;
2243          scalar->checkAttributes() ;
2244         
2245          if (isNewGrid) newGrid->addScalar(srcElementId) ;
2246        }
2247      }
2248     
2249      if (transformationPath.hasTransform() && hadTransform) hasRemainTransform=true ;
2250    } 
2251   
2252
2253    if (hadTransform)
2254    {
2255     
2256      if (!isSource)
2257      {
2258        shared_ptr<CGridAlgorithm> gridAlgorithm  ;
2259        if (isNewGrid)
2260        { 
2261          gridAlgorithm = algo->createGridAlgorithm(gridSrc, newGrid, pos) ;
2262          newGrid->setGridAlgorithm(gridAlgorithm);
2263        }
2264        else gridAlgorithm = newGrid->getGridAlgorithm() ;
2265
2266        shared_ptr<CTransformFilter> transformFilter = shared_ptr<CTransformFilter>(gridAlgorithm->createTransformFilter(gc, detectMissingValues, defaultValue)) ;
2267        outputFilter->connectOutput(transformFilter,0) ;
2268        if(graphEnabled)
2269        {
2270          transformFilter->graphEnabled=true;
2271          transformFilter->graphPackage = new CGraphPackage;
2272          transformFilter->graphPackage->inFields.push_back(field);
2273          transformFilter->graphPackage->show = !transformationGoing;
2274        }
2275       
2276        vector<string> auxFieldId = algo->getAuxFieldId() ; // better to do that at transformation not algo ??
2277        int i=1; 
2278        for (auto& it : auxFieldId)
2279        {
2280          CField* auxField = CField::get(it) ;
2281          auxField->buildWorkflowGraph(gc) ;
2282          auxField->getInstantDataFilter()->connectOutput(transformFilter,i) ;
2283          i++ ;
2284        }
2285        outputFilter = transformFilter ;
2286      }
2287
2288      if (hasRemainTransform)
2289      {
2290        transformationGoing = true;
2291        gridSrc=newGrid ;
2292        CField *field_bis = field;
2293        pair<shared_ptr<CFilter>, shared_ptr<CFilter> > filters = this->buildTransformationGraph(gc, isSource, gridSrc, detectMissingValues, defaultValue, newGrid, graphEnabled, field_bis) ;
2294        outputFilter->connectOutput(filters.first,0) ;
2295        outputFilter=filters.second ;
2296      }
2297      transformationGoing = false;
2298    }
2299     
2300    return {inputFilter,outputFilter} ;
2301  }
2302  CATCH_DUMP_ATTR
2303
2304
2305//****************************************************************
2306//****************************************************************
2307
2308//----------------------------------------------------------------
2309
2310  CGrid* CGrid::duplicateSentGrid(void)
2311  {
2312    CGrid* newGrid ;
2313    string sentGridId="sent__"+getId() ;
2314    if (has(sentGridId)) newGrid = get(sentGridId) ;
2315    else
2316    {
2317      newGrid = CGrid::create(sentGridId) ;
2318      for(auto element : elements_)
2319      {
2320        if (element.type==TYPE_DOMAIN)     
2321        {
2322          CDomain* domain = CDomain::create();
2323          domain->duplicateAttributes(element.domain) ;
2324          domain->setTemplateId(element.domain) ;
2325          if (domain->name.isEmpty()) domain->name = element.domain->getId() ;
2326          newGrid->addDomain(domain->getId()) ;
2327        }
2328        else if (element.type==TYPE_AXIS)     
2329        {
2330          CAxis* axis = CAxis::create();
2331          axis->duplicateAttributes(element.axis) ;
2332          axis->setTemplateId(element.axis) ;
2333          if (axis->name.isEmpty()) axis->name = element.axis->getId() ;
2334          newGrid->addAxis(axis->getId()) ;
2335        }
2336        else if (element.type==TYPE_SCALAR)     
2337        {
2338          CScalar* scalar = CScalar::create();
2339          scalar->duplicateAttributes(element.scalar) ;
2340          scalar->setTemplateId(element.scalar) ;
2341          if (scalar->name.isEmpty()) scalar->name = element.scalar->getId() ;
2342          newGrid->addScalar(scalar->getId()) ;
2343        }
2344      }
2345      newGrid->checkElementsAttributes() ;
2346    }
2347    return newGrid ;
2348  }
2349
2350
2351  void CGrid::setContextClient(CContextClient* contextClient)
2352  TRY
2353  {
2354    if (clientsSet.find(contextClient)==clientsSet.end())
2355    {
2356      clients.push_back(contextClient) ;
2357      clientsSet.insert(contextClient);
2358    }
2359    for (auto domain : getDomains()) domain->setContextClient(contextClient);
2360    for (auto axis : getAxis()) axis->setContextClient(contextClient);
2361    for (auto scalar : getScalars()) scalar->setContextClient(contextClient);
2362   
2363  }
2364  CATCH_DUMP_ATTR
2365
2366 
2367  void CGrid::computeGridLocalElements()
2368  {
2369    std::vector<CDomain*> domainList = this->getDomains();
2370    std::vector<CAxis*> axisList = this->getAxis();
2371    std::vector<CScalar*> scalarList = this->getScalars();
2372    auto domain=domainList.begin() ;
2373    auto axis=axisList.begin() ;
2374    auto scalar=scalarList.begin() ;
2375    vector<shared_ptr<CLocalElement>> elements;
2376    for(auto order : order_)
2377    {
2378      if (order==2) 
2379      {
2380        elements.push_back((*domain)->getLocalElement());
2381        domain++ ;
2382      }
2383      else if (order==1)
2384      {
2385        elements.push_back((*axis)->getLocalElement());
2386        axis++ ;
2387      }
2388      else if (order==0)
2389      { 
2390        elements.push_back((*scalar)->getLocalElement());
2391        scalar++ ;
2392      }
2393    }
2394    if (hasMask()) 
2395    {
2396      vector<bool> mask(getMask().getVector()) ;
2397      gridLocalElements_ = make_shared<CGridLocalElements>(elements, mask) ; 
2398    }
2399    else gridLocalElements_ = make_shared<CGridLocalElements>(elements) ; 
2400  }
2401
2402  void CGrid::computeModelToWorkflowConnector(void)
2403  {
2404    modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW,true) ;
2405  }
2406
2407  void CGrid::computeWorkflowToFullConnector(void)
2408  {
2409    workflowToFullConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::FULL) ;
2410  }
2411
2412  void CGrid::computeWorkflowToModelConnector(void)
2413  {
2414    workflowToModelConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::MODEL,true) ;
2415  }
2416
2417  void CGrid::computeFullToWorkflowConnector(void)
2418  {
2419    fullToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::FULL,CElementView::WORKFLOW) ;
2420  }
2421
2422  void CGrid::computeServerFromClientConnector(void)
2423  {
2424    vector<shared_ptr<CGathererConnector>> connectors ;
2425    for(auto& element : getElements())
2426    {
2427      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
2428      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
2429      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
2430    }
2431    serverFromClientConnector_ = make_shared<CGridGathererConnector>(connectors) ;
2432  }
2433
2434  void CGrid::computeServerToClientConnector(void)
2435  {
2436    vector<shared_ptr<CScattererConnector>> connectors ;
2437    for(auto& element : getElements())
2438    {
2439      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerToClientConnector()) ;
2440      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerToClientConnector()) ; 
2441      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerToClientConnector()) ; 
2442    }
2443    serverToClientConnector_ = make_shared<CGridScattererConnector>(connectors) ;
2444  }
2445
2446  void CGrid::computeClientFromClientConnector(void)
2447  {
2448    vector<shared_ptr<CGathererConnector>> connectors ;
2449    for(auto& element : getElements())
2450    {
2451      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
2452      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
2453      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
2454    }
2455    clientFromClientConnector_ = make_shared<CGridGathererConnector>(connectors) ;
2456  }
2457
2458 
2459} // namespace xios
Note: See TracBrowser for help on using the repository browser.