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

Last change on this file since 2247 was 2236, checked in by ymipsl, 3 years ago

Fix problem in remoteConnector when computing grid to sent to server.
Some optimisations when grid is not distributed need knowledge of the workflow view.
New CGridClientServerConnector class created based on CGridRemoteConnector.

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