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

Last change on this file since 2308 was 2305, checked in by ymipsl, 2 years ago

Fix bug when calling to "xios_solve_inheritance" that inhibit transformation chaining.

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