Salome HOME
719dd06469f44e31c27abcc5666a0e3cfb516f58
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingCartesianAMRMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay
20
21 #include "MEDCouplingCartesianAMRMesh.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingIMesh.hxx"
25 #include "MEDCouplingUMesh.hxx"
26
27 #include <limits>
28 #include <sstream>
29 #include <numeric>
30
31 using namespace ParaMEDMEM;
32
33 /// @cond INTERNAL
34
35 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithOverlap() const
36 {
37   return _mesh->getNumberOfCellsRecursiveWithOverlap();
38 }
39
40 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithoutOverlap() const
41 {
42   return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
43 }
44
45 int MEDCouplingCartesianAMRPatchGen::getMaxNumberOfLevelsRelativeToThis() const
46 {
47   return _mesh->getMaxNumberOfLevelsRelativeToThis();
48 }
49
50 MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCartesianAMRMeshGen *mesh)
51 {
52   if(!mesh)
53     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen constructor : input mesh is NULL !");
54   _mesh=mesh; _mesh->incrRef();
55 }
56
57 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
58 {
59   const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
60   if(!mesh)
61     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe const : the mesh is NULL !");
62   return mesh;
63 }
64
65 MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
66 {
67   MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
68     if(!mesh)
69       throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe : the mesh is NULL !");
70     return mesh;
71 }
72
73 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildren() const
74 {
75   std::vector<const BigMemoryObject *> ret;
76   if((const MEDCouplingCartesianAMRMeshGen *)_mesh)
77     ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
78   return ret;
79 }
80
81 /*!
82  * \param [in] mesh not null pointer of refined mesh replacing the cell range of \a father defined by the bottom left and top right just after.
83  * \param [in] bottomLeftTopRight a vector equal to the space dimension of \a mesh that specifies for each dimension, the included cell start of the range for the first element of the pair,
84  *                                a the end cell (\b excluded) of the range for the second element of the pair.
85  */
86 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight)
87 {
88   int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
89   if(dim!=dimExp)
90     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
91 }
92
93 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
94 {
95   return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
96 }
97
98 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
99 {
100   return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
101 }
102
103 /*!
104  * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
105  * the must be >= 0.
106  *
107  * \param [in] other - The other patch
108  * \param [in] ghostLev - The size of the neighborhood zone.
109  *
110  * \throw if \a this or \a other are invalid (end before start).
111  * \throw if \a ghostLev is \b not >= 0 .
112  * \throw if \a this and \a other have not the same space dimension.
113  */
114 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
115 {
116   if(ghostLev<0)
117     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !");
118   if(!other)
119     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !");
120   const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
121   const std::vector< std::pair<int,int> >& otherp(other->getBLTRRange());
122   std::size_t thispsize(thisp.size());
123   if(thispsize!=otherp.size())
124     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !");
125   for(std::size_t i=0;i<thispsize;i++)
126     {
127       const std::pair<int,int>& thispp(thisp[i]);
128       const std::pair<int,int>& otherpp(otherp[i]);
129       if(thispp.second<thispp.first)
130         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
131       if(otherpp.second<otherpp.first)
132         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
133       if(otherpp.first==thispp.second+ghostLev-1)
134         continue;
135       if(otherpp.second+ghostLev-1==thispp.first)
136         continue;
137       int start(std::max(thispp.first,otherpp.first)),end(std::min(thispp.second,otherpp.second));
138       if(end<start)
139         return false;
140     }
141   return true;
142 }
143
144 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
145 {
146   std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
147   ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
148   return ret;
149 }
150
151 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
152 {
153 }
154
155 std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
156 {
157   return sizeof(MEDCouplingCartesianAMRPatchGF);
158 }
159
160 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf)
161 {
162   if(!_gf)
163     throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
164   _gf->setData(this);
165 }
166
167 void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
168 {
169   _tlc.checkConst();
170 }
171
172 bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
173 {
174   bool ret(_tlc.keepTrackOfNewTL(gf));
175   if(ret)
176     {
177       _gf=gf;
178     }
179   return ret;
180 }
181
182 /// @endcond
183
184 int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const
185 {
186   return _mesh->getSpaceDimension();
187 }
188
189 void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFactors)
190 {
191   if(getSpaceDimension()!=(int)newFactors.size())
192     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : size of input factors is not equal to the space dimension !");
193   if(_factors.empty())
194     {
195       _factors=newFactors;
196       return ;
197     }
198   if(_factors==newFactors)
199     return ;
200   if(!_patches.empty())
201     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : modification of factors is not allowed when presence of patches !");
202   _factors=newFactors;
203   declareAsNew();
204 }
205
206 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
207 {
208   int ret(1);
209   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
210     ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
211   return ret;
212 }
213
214 /*!
215  * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this.
216  * The patches in \a this are ignored here.
217  * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap
218  */
219 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
220 {
221   return _mesh->getNumberOfCells();
222 }
223
224 /*!
225  * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this enlarged by \a ghostLev size
226  * to take into account of the ghost cells for future computation.
227  * The patches in \a this are ignored here.
228  *
229  * \sa getNumberOfCellsAtCurrentLevel
230  */
231 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
232 {
233   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
234   return tmp->getNumberOfCells();
235 }
236
237 /*!
238  * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels
239  * starting from this. The set of cells which size is returned here are generally overlapping each other.
240  */
241 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
242 {
243   int ret(_mesh->getNumberOfCells());
244   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
245     {
246       ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
247     }
248   return ret;
249 }
250
251 /*!
252  * This method returns the max number of cells covering all the space without overlapping.
253  * It returns the number of cells of the mesh with the highest resolution.
254  * The returned value is equal to the number of cells of mesh returned by buildUnstructured.
255  *
256  * \sa buildUnstructured
257  */
258 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
259 {
260   int ret(_mesh->getNumberOfCells());
261   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
262     {
263       ret-=(*it)->getNumberOfOverlapedCellsForFather();
264       ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
265     }
266   return ret;
267 }
268
269 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getFather() const
270 {
271   return _father;
272 }
273
274 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getGodFather() const
275 {
276   if(_father==0)
277     return this;
278   else
279     return _father->getGodFather();
280 }
281
282 /*!
283  * This method returns the level of \a this. 0 for god father. -1 for children of god father ...
284  */
285 int MEDCouplingCartesianAMRMeshGen::getAbsoluteLevel() const
286 {
287   if(_father==0)
288     return 0;
289   else
290     return _father->getAbsoluteLevel()-1;
291 }
292
293 /*!
294  * This method returns grids relative to god father to specified level \a absoluteLev.
295  *
296  * \return std::vector<MEDCouplingCartesianAMRPatchGen *> - objects in vector are to be managed (decrRef) by the caller.
297  */
298 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(int absoluteLev) const
299 {
300   if(absoluteLev<0)
301     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !");
302   if(_father)
303     return getGodFather()->retrieveGridsAt(absoluteLev);
304   //
305   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > rets;
306   retrieveGridsAtInternal(absoluteLev,rets);
307   std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
308   for(std::size_t i=0;i<rets.size();i++)
309     {
310       ret[i]=rets[i].retn();
311     }
312   return ret;
313 }
314
315 void MEDCouplingCartesianAMRMeshGen::detachFromFather()
316 {
317   _father=0;
318   declareAsNew();
319 }
320
321 /*!
322  * \param [in] bottomLeftTopRight a vector equal to the space dimension of \a mesh that specifies for each dimension, the included cell start of the range for the first element of the pair,
323  *                                a the end cell (\b excluded) of the range for the second element of the pair.
324  * \param [in] factors The factor of refinement per axis (different from 0).
325  */
326 void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
327 {
328   checkFactorsAndIfNotSetAssign(factors);
329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
330   mesh->refineWithFactor(factors);
331   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
332   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
333   _patches.push_back(elt);
334   declareAsNew();
335 }
336
337 /// @cond INTERNAL
338
339 class InternalPatch : public RefCountObjectOnly
340 {
341 public:
342   InternalPatch():_nb_of_true(0) { }
343   int getDimension() const { return (int)_part.size(); }
344   double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
345   int getNumberOfCells() const { return (int)_crit.size(); }
346   void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
347   std::vector<bool>& getCriterion() { return _crit; }
348   const std::vector<bool>& getConstCriterion() const { return _crit; }
349   void setPart(const std::vector< std::pair<int,int> >& part) { _part=part; }
350   std::vector< std::pair<int,int> >& getPart() { return _part; }
351   const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
352   bool presenceOfTrue() const { return _nb_of_true>0; }
353   std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
354   std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
355   double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
356   void zipToFitOnCriterion();
357   void updateNumberOfTrue() const;
358   MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
359   MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
360 protected:
361   ~InternalPatch() { }
362 private:
363   mutable int _nb_of_true;
364   std::vector<bool> _crit;
365   //! _part is global
366   std::vector< std::pair<int,int> > _part;
367 };
368
369 void InternalPatch::zipToFitOnCriterion()
370 {
371   std::vector<int> cgs(computeCGS());
372   std::vector<bool> newCrit;
373   std::vector< std::pair<int,int> > newPart,newPart2;
374   int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart));
375   MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
376   if(newNbOfTrue!=_nb_of_true)
377     throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
378   _crit=newCrit; _part=newPart2;
379 }
380
381 void InternalPatch::updateNumberOfTrue() const
382 {
383   _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
384 }
385
386 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
387 {
388   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
389   std::vector<int> cgs(computeCGS());
390   std::vector< std::pair<int,int> > newPart;
391   MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
392   MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion());
393   ret->setPart(partInGlobal);
394   ret->updateNumberOfTrue();
395   return ret;
396 }
397
398 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
399 {
400   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
401   (*ret)=*this;
402   return ret;
403 }
404
405 void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
406 {
407   cutFound=false; cutPlace=-1;
408   std::vector<double> ratio(rangeOfAxisId-1);
409   for(int id=0;id<rangeOfAxisId-1;id++)
410     {
411       double efficiency[2];
412       for(int h=0;h<2;h++)
413         {
414           std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
415           if(h==0)
416             rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id;
417           else
418             rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id;
419           MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
420           p->zipToFitOnCriterion();
421           //anouar rectH ?
422           efficiency[h]=p->getEfficiencyPerAxis(axisId);
423         }
424       ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]);
425     }
426   int minCellDirection(bso.getMinCellDirection()),indexMin(-1);
427   int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1));
428   std::vector<double> ratio_inner(dimRatioInner);
429   double minRatio(1.e10);
430   for(int i=0; i<dimRatioInner; i++)
431     {
432       if(ratio[minCellDirection-1+i]<minRatio)
433         {
434           minRatio=ratio[minCellDirection-1+i];
435           indexMin=i+minCellDirection;
436         }
437     }
438   cutFound=true; cutPlace=indexMin+patchToBeSplit->getConstPart()[axisId].first-1;
439 }
440
441 void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace)
442 {
443   cutPlace=-1; cutFound=false;
444   int minCellDirection(bso.getMinCellDirection());
445   const int dim(patchToBeSplit->getDimension());
446   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
447   for(int id=0;id<dim;id++)
448     {
449       const std::vector<int>& signature(signatures[id]);
450       std::vector<int> hole;
451       std::vector<double> distance;
452       int len((int)signature.size());
453       for(int i=0;i<len;i++)
454         if(signature[i]==0)
455           if(len>= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1)
456             hole.push_back(i);
457       if(!hole.empty())
458         {
459           double center(((double)len/2.));
460           for(std::size_t i=0;i<hole.size();i++)
461             distance.push_back(fabs(hole[i]+1.-center));
462
463           std::size_t posDistanceMin(std::distance(distance.begin(),std::min_element(distance.begin(),distance.end())));
464           cutFound=true;
465           axisId=id;
466           cutPlace=hole[posDistanceMin]+patchToBeSplit->getConstPart()[axisId].first+1;
467           return ;
468         }
469     }
470 }
471
472 void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId)
473 {
474   cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
475
476   const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
477   int sign,minCellDirection(bso.getMinCellDirection());
478   const int dim(patchToBeSplit->getDimension());
479
480   std::vector<int> zeroCrossDims(dim,-1);
481   std::vector<int> zeroCrossVals(dim,-1);
482   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
483   for (int id=0;id<dim;id++)
484     {
485       const std::vector<int>& signature(signatures[id]);
486
487       std::vector<int> derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ;
488       std::vector<double> distance ;
489
490       for (unsigned int i=1;i<signature.size()-1;i++)
491         derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
492
493       // Gradient absolute value
494       for ( unsigned int i=1;i<derivate_second_order.size();i++)
495         gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
496       if(derivate_second_order.empty())
497         continue;
498       for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
499         {
500           if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
501             sign = -1 ;
502           if (derivate_second_order[i]*derivate_second_order[i+1] > 0 )
503             sign = 1 ;
504           if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
505             sign = 0 ;
506           if ( sign==0 || sign==-1 )
507             if ( i >= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 )
508               {
509                 zero_cross.push_back(i) ;
510                 edge.push_back(gradient_absolute[i]) ;
511               }
512           signe_change.push_back(sign) ;
513         }
514       if ( zero_cross.size() > 0 )
515         {
516           int max_cross=*max_element(edge.begin(),edge.end()) ;
517           for (unsigned int i=0;i<edge.size();i++)
518             if (edge[i]==max_cross)
519               max_cross_list.push_back(zero_cross[i]+1) ;
520
521           double center((signature.size()/2.0));
522           for (unsigned int i=0;i<max_cross_list.size();i++)
523             distance.push_back(fabs(max_cross_list[i]+1-center));
524
525           float distance_min=*min_element(distance.begin(),distance.end()) ;
526           int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
527           int best_place = max_cross_list[pos_distance_min] + part[id].first ;
528           if ( max_cross >=0 )
529             {
530               zeroCrossDims[id] = best_place ;
531               zeroCrossVals[id] = max_cross ;
532             }
533         }
534       derivate_second_order.clear() ;
535       gradient_absolute.clear() ;
536       signe_change.clear() ;
537       zero_cross.clear() ;
538       edge.clear() ;
539       max_cross_list.clear() ;
540       distance.clear() ;
541     }
542
543   if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1  )
544     {
545       int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ;
546
547       if (zeroCrossVals[0]==max_cross_dims &&  zeroCrossVals[1]==max_cross_dims )
548         {
549           int nl_left(part[0].second-part[0].first);
550           int nc_left(part[1].second-part[1].first);
551           if ( nl_left >=  nc_left )
552             max_cross_dims = 0 ;
553           else
554             max_cross_dims = 1 ;
555         }
556       else
557         max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin();
558       cutFound=true;
559       cutPlace=zeroCrossDims[max_cross_dims];
560       axisId=max_cross_dims ;
561     }
562 }
563
564 void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
565 {
566   cutFound=false;
567   if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd())
568     {
569       if(rangeOfAxisId>=2*bso.getMinCellDirection())
570         {
571           cutFound=true;
572           cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
573         }
574     }
575   else
576     {
577       if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells())
578         {
579           DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace);
580         }
581     }
582 }
583
584 MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
585 {
586   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
587   ret->incrRef();
588   return ret;
589 }
590
591 void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
592 {
593   MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
594   std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
595   std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
596   leftRect[axisId].second=cutPlace+1;
597   rightRect[axisId].first=cutPlace+1;
598   leftPart=patchToBeSplit->extractPart(leftRect);
599   rightPart=patchToBeSplit->extractPart(rightRect);
600   leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion();
601   listOfPatches.push_back(leftPart);
602   listOfPatches.push_back(rightPart);
603 }
604
605 /// @endcond
606
607 /*!
608  * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion array as a field on cells on this level.
609  */
610 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
611 {
612   int nbCells(getNumberOfCellsAtCurrentLevel());
613   if(nbCells!=(int)criterion.size())
614     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
615   _patches.clear();
616   std::vector<int> cgs(_mesh->getCellGridStructure());
617   std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
618   //
619   MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
620   p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart()));
621   if(p->presenceOfTrue())
622     listOfPatches.push_back(p);
623   while(!listOfPatches.empty())
624     {
625       std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
626       for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
627         {
628           //
629           int axisId,rangeOfAxisId,cutPlace;
630           bool cutFound;
631           MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId);
632           if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()<bso.getMaxCells())
633             { listOfPatchesOK.push_back(DealWithNoCut(*it)); continue; }//action 1
634           FindHole(bso,*it,axisId,cutFound,cutPlace);//axisId overwritten here if FindHole equal to true !
635           if(cutFound)
636             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
637           FindInflection(bso,*it,cutFound,cutPlace,axisId);//axisId overwritten here if cutFound equal to true !
638           if(cutFound)
639             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
640           TryAction4(bso,*it,axisId,rangeOfAxisId,cutFound,cutPlace);
641           if(cutFound)
642             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
643           listOfPatchesOK.push_back(DealWithNoCut(*it));
644         }
645       listOfPatches=listOfPatchesTmp;
646     }
647   for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
648     addPatch((*it)->getConstPart(),factors);
649   declareAsNew();
650 }
651
652 /*!
653  * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion array as a field on cells on this level.
654  */
655 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
656 {
657   if(!criterion || !criterion->isAllocated())
658     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
659   std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
660   createPatchesFromCriterion(bso,crit,factors);
661   declareAsNew();
662 }
663
664 void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
665 {
666   _patches.clear();
667   declareAsNew();
668 }
669
670 void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
671 {
672   checkPatchId(patchId);
673   int sz((int)_patches.size()),j(0);
674   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
675   for(int i=0;i<sz;i++)
676     if(i!=patchId)
677       patches[j++]=_patches[i];
678   (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
679   _patches=patches;
680   declareAsNew();
681 }
682
683 int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
684 {
685   return (int)_patches.size();
686 }
687
688 int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
689 {
690   int ret(0);
691   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
692     {
693       if((*it)->getMesh()==mesh)
694         return ret;
695     }
696   throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
697 }
698
699 std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
700 {
701   std::size_t sz(_patches.size());
702   std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
703   for(std::size_t i=0;i<sz;i++)
704     ret[i]=_patches[i];
705   return ret;
706 }
707
708 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const
709 {
710   checkPatchId(patchId);
711   return _patches[patchId];
712 }
713
714 /*!
715  * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1).
716  * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !).
717  */
718 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
719 {
720   if(ghostLev<0)
721     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::isPatchInNeighborhoodOf : the ghost size must be >=0 !");
722   const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
723   if(_factors.empty())
724     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::isPatchInNeighborhoodOf : no factors defined !");
725   int ghostLevInPatchRef;
726   if(ghostLev==0)
727     ghostLevInPatchRef=0;
728   else
729     {
730       ghostLevInPatchRef=(ghostLev-1)/_factors[0]+1;
731       for(std::size_t i=0;i<_factors.size();i++)
732         ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/_factors[i]+1);
733     }
734   return p1->isInMyNeighborhood(p2,ghostLevInPatchRef);
735 }
736
737 /*!
738  * This method creates a new cell field array on given \a patchId patch in \a this starting from a coarse cell field on \a this \a cellFieldOnThis.
739  * This method can be seen as a fast projection from the cell field \a cellFieldOnThis on \c this->getImageMesh() to a refined part of \a this
740  * defined by the patch with id \a patchId.
741  *
742  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
743  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
744  * \return DataArrayDouble * - The array of the cell field on the requested patch
745  *
746  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
747  * \throw if \a cellFieldOnThis is NULL or not allocated
748  * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine
749  */
750 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const
751 {
752   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
753     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
754   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
755   const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
756   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
757   ret->copyStringInfoFrom(*cellFieldOnThis);
758   MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
759   return ret.retn();
760 }
761
762 /*!
763  * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of creating a new instance
764  * it fills the value into the \a cellFieldOnPatch data.
765  *
766  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
767  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
768  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
769  *
770  * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
771  */
772 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const
773 {
774   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
775     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
776   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
777   MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
778 }
779
780 /*!
781  * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the
782  * potential neighbor patches covered by the ghost cells of patch with id \a patchId.
783  *
784  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
785  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
786  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
787  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
788  *
789  * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
790  */
791 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
792 {
793   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
794     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
795   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
796   MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
797 }
798
799 /*!
800  * This method is equivalent to  fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
801  * in \a cellFieldOnPatch.
802  *
803  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
804  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
805  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled \b only \b in \b the \b ghost \b zone.
806  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
807  */
808 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
809 {
810   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
811     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
812   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
813   MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
814 }
815
816 /*!
817  * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
818  * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
819  *
820  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
821  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
822  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
823  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
824  * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
825  *
826  * \sa fillCellFieldOnPatchOnlyGhostAdv
827  */
828 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
829 {
830   int nbp(getNumberOfPatches());
831   if(nbp!=(int)arrsOnPatches.size())
832     {
833       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
834       throw INTERP_KERNEL::Exception(oss.str().c_str());
835     }
836   DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
837   // first, do as usual
838   fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev);
839   fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
840 }
841
842 /*!
843  * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
844  * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
845  */
846 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
847 {
848   int nbp(getNumberOfPatches()),dim(getSpaceDimension());
849   if(nbp!=(int)arrsOnPatches.size())
850     {
851       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
852       throw INTERP_KERNEL::Exception(oss.str().c_str());
853     }
854   DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
855   const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
856   const std::vector< std::pair<int,int> >& refBLTR(refP->getBLTRRange());//[(1,4),(2,4)]
857   std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(refBLTR));//[3,2]
858   std::transform(dimsCoarse.begin(),dimsCoarse.end(),_factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
859   std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
860   std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
861   std::vector<int> fakeFactors(dim,1);
862   //
863   for(int i=0;i<nbp;i++)
864     {
865       if(i!=patchId)
866         if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
867           {
868             const MEDCouplingCartesianAMRPatch *otherP(getPatch(i));
869             const std::vector< std::pair<int,int> >& otherBLTR(otherP->getBLTRRange());//[(4,5),(3,4)]
870             std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
871             MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(refBLTR,otherBLTR,tmp0,false);//tmp0=[(3,4),(1,2)]
872             ApplyFactorsOnCompactFrmt(tmp0,_factors);//tmp0=[(12,16),(4,8)]
873             ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
874             std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
875             MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(otherBLTR,refBLTR,tmp1,false);//tmp1=[(-3,0),(-1,1)]
876             ApplyFactorsOnCompactFrmt(tmp1,_factors);//tmp1=[(-12,-4),(-4,0)]
877             MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
878             //
879             std::vector< std::pair<int,int> > dimsFine(otherBLTR);
880             ApplyFactorsOnCompactFrmt(dimsFine,_factors);
881             ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
882             //
883             MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),arrsOnPatches[i],tmp2));
884             MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,theFieldToFill);
885           }
886     }
887 }
888
889 /*!
890  * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
891  *
892  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
893  * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
894  * \param [in,out] cellFieldOnThis The array of the cell field on \a this to be updated only on the part concerning the patch with id \a patchId.
895  *
896  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
897  * \throw if \a cellFieldOnPatch is NULL or not allocated
898  * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
899  */
900 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const
901 {
902   if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
903       throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
904   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
905   MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
906 }
907
908 /*!
909  * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this
910  * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch.
911  *
912  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
913  * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
914  * \param [in,out] cellFieldOnThis The array of the cell field on \a this to be updated only on the part concerning the patch with id \a patchId.
915  * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
916  *
917  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
918  * \throw if \a cellFieldOnPatch is NULL or not allocated
919  * \sa fillCellFieldComingFromPatch
920  */
921 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) const
922 {
923   if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
924     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
925   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
926   MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
927 }
928
929 /*!
930  * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is
931  * defined by ghostLev.
932  *
933  * \param [in] patchId - the id of the considered patch.
934  * \param [in] ghostLev - the size of the neighborhood.
935  * \return DataArrayInt * - the newly allocated array containing the list of patches in the neighborhood of the considered patch. This array is to be deallocated by the caller.
936  */
937 DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const
938 {
939   int nbp(getNumberOfPatches());
940   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
941   for(int i=0;i<nbp;i++)
942     {
943       if(i!=patchId)
944         if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
945           ret->pushBackSilent(i);
946     }
947   return ret.retn();
948 }
949
950 MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
951 {
952   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
953   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
954   std::vector<int> cgs(_mesh->getCellGridStructure());
955   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
956   std::size_t ii(0);
957   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
958     {
959       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
960       msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
961     }
962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
963   msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
964   std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
965   for(std::size_t i=0;i<msSafe.size();i++)
966     ms[i]=msSafe[i];
967   return MEDCouplingUMesh::MergeUMeshes(ms);
968 }
969
970 /*!
971  * This method returns a mesh containing as cells that there is patches at the current level.
972  * The patches are seen like 'boxes' that is too say the refinement will not appear here.
973  *
974  * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
975  */
976 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
977 {
978   std::vector<const MEDCoupling1SGTUMesh *> cells;
979   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
980   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
981     {
982       const MEDCouplingCartesianAMRPatch *patch(*it);
983       if(patch)
984         {
985           MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
986           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
987           cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
988         }
989     }
990   return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
991 }
992
993 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
994 {
995   std::vector<const MEDCoupling1SGTUMesh *> patches;
996   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > patchesSafe;
997   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
998       {
999         const MEDCouplingCartesianAMRPatch *patch(*it);
1000         if(patch)
1001           {
1002             MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
1003             patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
1004           }
1005       }
1006     return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
1007 }
1008
1009 /*!
1010  * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
1011  * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
1012  * \sa buildUnstructured
1013  */
1014 MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
1015 {
1016   if(recurseArrs.empty())
1017     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
1018   //
1019   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1020   std::vector<int> cgs(_mesh->getCellGridStructure());
1021   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
1022   std::size_t ii(0);
1023   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1024     {
1025       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1026       std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
1027       msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
1028     }
1029   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1030   //
1031   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
1032   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
1033   arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
1034   ret->setArray(arr2);
1035   ret->setName(arr2->getName());
1036   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1038   ret->setMesh(mesh);
1039   msSafe[0]=ret;
1040   //
1041   std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
1042   for(std::size_t i=0;i<msSafe.size();i++)
1043     ms[i]=msSafe[i];
1044   //
1045   return MEDCouplingFieldDouble::MergeFields(ms);
1046 }
1047
1048 /*!
1049  * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
1050  * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
1051  */
1052 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const
1053 {
1054   std::vector<int> st(_mesh->getCellGridStructure());
1055   std::vector< std::pair<int,int> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
1056   std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus<int>(),2*ghostSz));
1057   ApplyGhostOnCompactFrmt(p,ghostSz);
1058   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
1059   return ret.retn();
1060 }
1061
1062 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1063                                                                const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
1064 {
1065   _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1066 }
1067
1068 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):_father(father)
1069 {
1070   if(!_father)
1071     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : empty father !");
1072   if(!mesh)
1073     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
1074   mesh->checkCoherency();
1075   _mesh=mesh; _mesh->incrRef();
1076 }
1077
1078 void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const
1079 {
1080   int sz(getNumberOfPatches());
1081   if(patchId<0 || patchId>=sz)
1082     {
1083       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
1084       throw INTERP_KERNEL::Exception(oss.str().c_str());
1085     }
1086 }
1087
1088 void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector<int>& factors)
1089 {
1090   if(getSpaceDimension()!=(int)factors.size())
1091     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !");
1092   if(_factors.empty())
1093     {
1094       _factors=factors;
1095     }
1096   else
1097     {
1098       if(_factors!=factors)
1099         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : the factors ");
1100     }
1101 }
1102
1103 void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> >& grids) const
1104 {
1105   if(lev==0)
1106     {
1107       const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
1108       MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
1109       grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
1110     }
1111   else if(lev==1)
1112     {
1113       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1114         {
1115           const MEDCouplingCartesianAMRPatch *pt(*it);
1116           if(pt)
1117             {
1118               MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> tmp1(*it);
1119               grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
1120             }
1121         }
1122     }
1123   else
1124     {
1125       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1126         {
1127           const MEDCouplingCartesianAMRPatch *pt(*it);
1128           if(pt)
1129             pt->getMesh()->retrieveGridsAtInternal(lev-1,grids);
1130         }
1131     }
1132 }
1133
1134 /*!
1135  * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
1136  * \param [in] factors - the factors per axis.
1137  */
1138 void MEDCouplingCartesianAMRMeshGen::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
1139 {
1140   std::size_t sz(factors.size());
1141   if(sz!=partBeforeFact.size())
1142     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
1143   for(std::size_t i=0;i<sz;i++)
1144     {
1145       partBeforeFact[i].first*=factors[i];
1146       partBeforeFact[i].second*=factors[i];
1147     }
1148 }
1149
1150 /*!
1151  * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
1152  * \param [in] ghostSize - the ghost size of zone for all axis.
1153  */
1154 void MEDCouplingCartesianAMRMeshGen::ApplyGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
1155 {
1156   if(ghostSize<0)
1157     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !");
1158   std::size_t sz(partBeforeFact.size());
1159   for(std::size_t i=0;i<sz;i++)
1160     {
1161       partBeforeFact[i].first+=ghostSize;
1162       partBeforeFact[i].second+=ghostSize;
1163     }
1164 }
1165
1166 /*!
1167  * This method is different than ApplyGhostOnCompactFrmt. The \a partBeforeFact parameter is enlarger contrary to ApplyGhostOnCompactFrmt.
1168  *
1169  * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
1170  * \param [in] ghostSize - the ghost size of zone for all axis.
1171  */
1172 void MEDCouplingCartesianAMRMeshGen::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
1173 {
1174   if(ghostSize<0)
1175     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
1176   std::size_t sz(partBeforeFact.size());
1177   for(std::size_t i=0;i<sz;i++)
1178     {
1179       partBeforeFact[i].first-=ghostSize;
1180       partBeforeFact[i].second+=ghostSize;
1181     }
1182 }
1183
1184 /*!
1185  * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
1186  * Elements in \a all are expected to be sorted from god father to most refined structure.
1187  */
1188 std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
1189 {
1190   int maxLev(getMaxNumberOfLevelsRelativeToThis());
1191   std::vector<const DataArrayDouble *> ret;
1192   std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
1193   std::size_t kk(0);
1194   for(int i=0;i<maxLev;i++)
1195     {
1196       std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
1197       for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
1198         {
1199           if((*it)==head || head->isObjectInTheProgeny(*it))
1200             ret.push_back(all[kk]);
1201           kk++;
1202           std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
1203           for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
1204             {
1205               const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
1206               meshesTmp.push_back(mesh);
1207             }
1208         }
1209       meshes=meshesTmp;
1210     }
1211   if(kk!=all.size())
1212     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
1213   return ret;
1214 }
1215
1216 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
1217 {
1218   return sizeof(MEDCouplingCartesianAMRMeshGen);
1219 }
1220
1221 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildren() const
1222 {
1223   std::vector<const BigMemoryObject *> ret;
1224   if((const MEDCouplingIMesh *)_mesh)
1225     ret.push_back((const MEDCouplingIMesh *)_mesh);
1226   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1227     {
1228       if((const MEDCouplingCartesianAMRPatch*)*it)
1229         ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
1230     }
1231   return ret;
1232 }
1233
1234 void MEDCouplingCartesianAMRMeshGen::updateTime() const
1235 {
1236   if((const MEDCouplingIMesh *)_mesh)
1237     updateTimeWith(*_mesh);
1238   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1239     {
1240       const MEDCouplingCartesianAMRPatch *elt(*it);
1241       if(!elt)
1242         continue;
1243       const MEDCouplingCartesianAMRMeshGen *mesh(elt->getMesh());
1244       if(mesh)
1245         updateTimeWith(*mesh);
1246     }
1247 }
1248
1249 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(father,mesh)
1250 {
1251 }
1252
1253 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1254                                                               const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1255 {
1256   return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1257 }
1258
1259 void MEDCouplingCartesianAMRMesh::setData(MEDCouplingDataForGodFather *data)
1260 {
1261   MEDCouplingDataForGodFather *myData(_data);
1262   if(myData==data)
1263     return ;
1264   if(myData)
1265     myData->changeGodFather(0);
1266   _data=data;
1267   if(data)
1268     data->incrRef();
1269 }
1270
1271 void MEDCouplingCartesianAMRMesh::allocData(int ghostLev) const
1272 {
1273   checkData();
1274   _data->alloc(ghostLev);
1275 }
1276
1277 void MEDCouplingCartesianAMRMesh::deallocData() const
1278 {
1279   checkData();
1280   _data->dealloc();
1281 }
1282
1283 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1284                                                          const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
1285 {
1286 }
1287
1288 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
1289 {
1290   std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren());
1291   const MEDCouplingDataForGodFather *pt(_data);
1292   if(pt)
1293     ret.push_back(pt);
1294   return ret;
1295 }
1296
1297 void MEDCouplingCartesianAMRMesh::checkData() const
1298 {
1299   const MEDCouplingDataForGodFather *data(_data);
1300   if(!data)
1301     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkData : no data set !");
1302 }
1303
1304 MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()
1305 {
1306   MEDCouplingDataForGodFather *data(_data);
1307   if(data)
1308     data->changeGodFather(0);
1309 }