Salome HOME
OK for first tests in 3D.
[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 "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingIMesh.hxx"
24 #include "MEDCouplingUMesh.hxx"
25
26 #include <limits>
27 #include <sstream>
28 #include <numeric>
29
30 using namespace ParaMEDMEM;
31
32 /// @cond INTERNAL
33
34 /*!
35  * \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.
36  * \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,
37  *                                a the end cell (\b excluded) of the range for the second element of the pair.
38  * \param [in] factors The refinement per axis relative to the father of \a this.
39  */
40 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMesh *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
41 {
42   if(!mesh)
43     throw INTERP_KERNEL::Exception("EDCouplingCartesianAMRPatch constructor : input mesh is NULL !");
44   _mesh=mesh; _mesh->incrRef();
45   int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
46   if(dim!=dimExp)
47     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
48   _bl_tr=bottomLeftTopRight;
49   if((int)factors.size()!=dimExp)
50     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input factors per axis size mismatches !");
51   _factors=factors;
52 }
53
54 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithOverlap() const
55 {
56   return _mesh->getNumberOfCellsRecursiveWithOverlap();
57 }
58
59 int MEDCouplingCartesianAMRPatch::getNumberOfCellsRecursiveWithoutOverlap() const
60 {
61   return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
62 }
63
64 int MEDCouplingCartesianAMRPatch::getMaxNumberOfLevelsRelativeToThis() const
65 {
66   return _mesh->getMaxNumberOfLevelsRelativeToThis();
67 }
68
69 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
70 {
71   return _mesh->addPatch(bottomLeftTopRight,factors);
72 }
73
74 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
75 {
76   return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
77 }
78
79 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
80 {
81   std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
82   ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
83   return ret;
84 }
85
86 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatch::getDirectChildren() const
87 {
88   std::vector<const BigMemoryObject *> ret;
89   if((const MEDCouplingCartesianAMRMesh *)_mesh)
90     ret.push_back((const MEDCouplingCartesianAMRMesh *)_mesh);
91   return ret;
92 }
93
94 /// @endcond
95
96
97 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
98                                                               const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
99 {
100   return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
101 }
102
103 int MEDCouplingCartesianAMRMesh::getSpaceDimension() const
104 {
105   return _mesh->getSpaceDimension();
106 }
107
108 int MEDCouplingCartesianAMRMesh::getMaxNumberOfLevelsRelativeToThis() const
109 {
110   int ret(1);
111   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
112     ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
113   return ret;
114 }
115
116 int MEDCouplingCartesianAMRMesh::getNumberOfCellsAtCurrentLevel() const
117 {
118   return _mesh->getNumberOfCells();
119 }
120
121 int MEDCouplingCartesianAMRMesh::getNumberOfCellsRecursiveWithOverlap() const
122 {
123   int ret(_mesh->getNumberOfCells());
124   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
125     {
126       ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
127     }
128   return ret;
129 }
130
131 int MEDCouplingCartesianAMRMesh::getNumberOfCellsRecursiveWithoutOverlap() const
132 {
133   int ret(_mesh->getNumberOfCells());
134   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
135     {
136       ret-=(*it)->getNumberOfOverlapedCellsForFather();
137       ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
138     }
139   return ret;
140 }
141
142 const MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::getFather() const
143 {
144   return _father;
145 }
146
147 const MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::getGodFather() const
148 {
149   if(_father==0)
150     return this;
151   else
152     return _father->getGodFather();
153 }
154
155 void MEDCouplingCartesianAMRMesh::detachFromFather()
156 {
157   _father=0;
158 }
159
160 /*!
161  * \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,
162  *                                a the end cell (\b excluded) of the range for the second element of the pair.
163  * \param [in] factors The != 0 factor of refinement per axis.
164  */
165 void MEDCouplingCartesianAMRMesh::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
166 {
167   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
168   mesh->refineWithFactor(factors);
169   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMesh> zeMesh(new MEDCouplingCartesianAMRMesh(this,mesh));
170   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight,factors));
171   _patches.push_back(elt);
172 }
173
174 /// @cond INTERNAL
175
176 class InternalPatch : public RefCountObjectOnly
177 {
178 public:
179   InternalPatch():_nb_of_true(0) { }
180   int getDimension() const { return (int)_part.size(); }
181   double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
182   int getNumberOfCells() const { return (int)_crit.size(); }
183   void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
184   std::vector<bool>& getCriterion() { return _crit; }
185   const std::vector<bool>& getConstCriterion() const { return _crit; }
186   void setPart(const std::vector< std::pair<int,int> >& part) { _part=part; }
187   std::vector< std::pair<int,int> >& getPart() { return _part; }
188   const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
189   bool presenceOfTrue() const { return _nb_of_true>0; }
190   std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
191   std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
192   double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
193   void zipToFitOnCriterion();
194   void updateNumberOfTrue() const;
195   MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
196   MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
197 protected:
198   ~InternalPatch() { }
199 private:
200   mutable int _nb_of_true;
201   std::vector<bool> _crit;
202   //! _part is global
203   std::vector< std::pair<int,int> > _part;
204 };
205
206 void InternalPatch::zipToFitOnCriterion()
207 {
208   std::vector<int> cgs(computeCGS());
209   std::vector<bool> newCrit;
210   std::vector< std::pair<int,int> > newPart,newPart2;
211   int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart));
212   MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
213   if(newNbOfTrue!=_nb_of_true)
214     throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
215   _crit=newCrit; _part=newPart2;
216 }
217
218 void InternalPatch::updateNumberOfTrue() const
219 {
220   _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
221 }
222
223 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
224 {
225   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
226   std::vector<int> cgs(computeCGS());
227   std::vector< std::pair<int,int> > newPart;
228   MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
229   MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion());
230   ret->setPart(partInGlobal);
231   ret->updateNumberOfTrue();
232   return ret;
233 }
234
235 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
236 {
237   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
238   (*ret)=*this;
239   return ret;
240 }
241
242 void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
243 {
244   cutFound=false; cutPlace=-1;
245   std::vector<double> ratio(rangeOfAxisId-1);
246   for(int id=0;id<rangeOfAxisId-1;id++)
247     {
248       double efficiency[2];
249       for(int h=0;h<2;h++)
250         {
251           std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
252           if(h==0)
253             rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id;
254           else
255             rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id;
256           MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
257           p->zipToFitOnCriterion();
258           //anouar rectH ?
259           efficiency[h]=p->getEfficiencyPerAxis(axisId);
260         }
261       ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]);
262     }
263   int minCellDirection(bso.getMinCellDirection()),indexMin(-1);
264   int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1));
265   std::vector<double> ratio_inner(dimRatioInner);
266   double minRatio(1.e10);
267   for(int i=0; i<dimRatioInner; i++)
268     {
269       if(ratio[minCellDirection-1+i]<minRatio)
270         {
271           minRatio=ratio[minCellDirection-1+i];
272           indexMin=i+minCellDirection;
273         }
274     }
275   cutFound=true; cutPlace=indexMin+patchToBeSplit->getConstPart()[axisId].first-1;
276 }
277
278 void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace)
279 {
280   cutPlace=-1; cutFound=false;
281   int minCellDirection(bso.getMinCellDirection());
282   const int dim(patchToBeSplit->getDimension());
283   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
284   for(int id=0;id<dim;id++)
285     {
286       const std::vector<int>& signature(signatures[id]);
287       std::vector<int> hole;
288       std::vector<double> distance;
289       int len((int)signature.size());
290       for(int i=0;i<len;i++)
291         if(signature[i]==0)
292           if(len>= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1)
293             hole.push_back(i);
294       if(!hole.empty())
295         {
296           double center(((double)len/2.));
297           for(std::size_t i=0;i<hole.size();i++)
298             distance.push_back(fabs(hole[i]+1.-center));
299
300           std::size_t posDistanceMin(std::distance(distance.begin(),std::min_element(distance.begin(),distance.end())));
301           cutFound=true;
302           axisId=id;
303           cutPlace=hole[posDistanceMin]+patchToBeSplit->getConstPart()[axisId].first+1;
304           return ;
305         }
306     }
307 }
308
309 void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId)
310 {
311   cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
312
313   const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
314   int sign,minCellDirection(bso.getMinCellDirection());
315   const int dim(patchToBeSplit->getDimension());
316
317   std::vector<int> zeroCrossDims(dim,-1);
318   std::vector<int> zeroCrossVals(dim,-1);
319   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
320   for (int id=0;id<dim;id++)
321     {
322       const std::vector<int>& signature(signatures[id]);
323
324       std::vector<int> derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ;
325       std::vector<double> distance ;
326
327       for (unsigned int i=1;i<signature.size()-1;i++)
328         derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
329
330       // Gradient absolute value
331       for ( unsigned int i=1;i<derivate_second_order.size();i++)
332         gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
333       if(derivate_second_order.empty())//tony -> si empty le reste plante !
334         continue;
335       for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
336         {
337           if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
338             sign = -1 ;
339           if (derivate_second_order[i]*derivate_second_order[i+1] > 0 )
340             sign = 1 ;
341           if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
342             sign = 0 ;
343           if ( sign==0 || sign==-1 )
344             if ( i >= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 )
345               {
346                 zero_cross.push_back(i) ;
347                 edge.push_back(gradient_absolute[i]) ;
348               }
349           signe_change.push_back(sign) ;
350         }
351       if ( zero_cross.size() > 0 )
352         {
353           int max_cross=*max_element(edge.begin(),edge.end()) ;
354           for (unsigned int i=0;i<edge.size();i++)
355             if (edge[i]==max_cross)
356               max_cross_list.push_back(zero_cross[i]+1) ;
357
358           double center((signature.size()/2.0));
359           for (unsigned int i=0;i<max_cross_list.size();i++)
360             distance.push_back(fabs(max_cross_list[i]+1-center));
361
362           float distance_min=*min_element(distance.begin(),distance.end()) ;
363           int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
364           int best_place = max_cross_list[pos_distance_min] + part[id].first ;
365           if ( max_cross >=0 )
366             {
367               zeroCrossDims[id] = best_place ;
368               zeroCrossVals[id] = max_cross ;
369             }
370         }
371       derivate_second_order.clear() ;
372       gradient_absolute.clear() ;
373       signe_change.clear() ;
374       zero_cross.clear() ;
375       edge.clear() ;
376       max_cross_list.clear() ;
377       distance.clear() ;
378     }
379
380   if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1  )
381     {
382       int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ;
383
384       if (zeroCrossVals[0]==max_cross_dims &&  zeroCrossVals[1]==max_cross_dims )
385         {
386           int nl_left(part[0].second-part[0].first);
387           int nc_left(part[1].second-part[1].first);
388           if ( nl_left >=  nc_left )
389             max_cross_dims = 0 ;
390           else
391             max_cross_dims = 1 ;
392         }
393       else
394         max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin();
395       cutFound=true;
396       cutPlace=zeroCrossDims[max_cross_dims];
397       axisId=max_cross_dims ;
398     }
399 }
400
401 void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
402 {
403   cutFound=false;
404   if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd())
405     {
406       if(rangeOfAxisId>=2*bso.getMinCellDirection())
407         {
408           cutFound=true;
409           cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
410         }
411     }
412   else
413     {
414       if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells())
415         {
416           DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace);
417         }
418     }
419 }
420
421 MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
422 {
423   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
424   ret->incrRef();
425   return ret;
426 }
427
428 void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
429 {
430   MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
431   std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
432   std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
433   leftRect[axisId].second=cutPlace+1;
434   rightRect[axisId].first=cutPlace+1;
435   leftPart=patchToBeSplit->extractPart(leftRect);
436   rightPart=patchToBeSplit->extractPart(rightRect);
437   leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion();
438   listOfPatches.push_back(leftPart);
439   listOfPatches.push_back(rightPart);
440 }
441
442 /// @endcond
443
444 /*!
445  * 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.
446  */
447 void MEDCouplingCartesianAMRMesh::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
448 {
449   if(!criterion || !criterion->isAllocated())
450     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
451   int nbCells(getNumberOfCellsAtCurrentLevel());
452   if(nbCells!=criterion->getNumberOfTuples())
453     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 !");
454   _patches.clear();
455   //
456   std::vector<int> cgs(_mesh->getCellGridStructure());
457   std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
458   std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
459   //
460   MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
461   p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,crit,p->getCriterion(),p->getPart()));
462   if(p->presenceOfTrue())
463     listOfPatches.push_back(p);
464   while(!listOfPatches.empty())
465     {
466       std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
467       for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
468         {
469           //
470           int axisId,rangeOfAxisId,cutPlace;
471           bool cutFound;
472           MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId);
473           if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()<bso.getMaxCells())
474             { listOfPatchesOK.push_back(DealWithNoCut(*it)); continue; }//action 1
475           FindHole(bso,*it,axisId,cutFound,cutPlace);//axisId overwritten here if FindHole equal to true !
476           if(cutFound)
477             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
478           FindInflection(bso,*it,cutFound,cutPlace,axisId);//axisId overwritten here if cutFound equal to true !
479           if(cutFound)
480             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
481           TryAction4(bso,*it,axisId,rangeOfAxisId,cutFound,cutPlace);
482           if(cutFound)
483             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
484           listOfPatchesOK.push_back(DealWithNoCut(*it));
485         }
486       listOfPatches=listOfPatchesTmp;
487     }
488   for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
489     addPatch((*it)->getConstPart(),factors);
490 }
491
492 void MEDCouplingCartesianAMRMesh::removePatch(int patchId)
493 {
494   checkPatchId(patchId);
495   int sz((int)_patches.size()),j(0);
496   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
497   for(int i=0;i<sz;i++)
498     if(i!=patchId)
499       patches[j++]=_patches[i];
500   (const_cast<MEDCouplingCartesianAMRMesh *>(_patches[patchId]->getMesh()))->detachFromFather();
501   _patches=patches;
502   declareAsNew();
503 }
504
505 int MEDCouplingCartesianAMRMesh::getNumberOfPatches() const
506 {
507   return (int)_patches.size();
508 }
509
510 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMesh::getPatch(int patchId) const
511 {
512   checkPatchId(patchId);
513   return _patches[patchId];
514 }
515
516 MEDCouplingUMesh *MEDCouplingCartesianAMRMesh::buildUnstructured() const
517 {
518   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
519   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
520   std::vector<int> cgs(_mesh->getCellGridStructure());
521   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
522   std::size_t ii(0);
523   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
524     {
525       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
526       msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
527     }
528   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
529   msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
530   std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
531   for(std::size_t i=0;i<msSafe.size();i++)
532     ms[i]=msSafe[i];
533   return MEDCouplingUMesh::MergeUMeshes(ms);
534 }
535
536 /*!
537  * This method returns a mesh containing as cells that there is patches at the current level.
538  * The patches are seen like 'boxes' that is too say the refinement will not appear here.
539  *
540  * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
541  */
542 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMesh::buildMeshFromPatchEnvelop() const
543 {
544   std::vector<const MEDCoupling1SGTUMesh *> cells;
545   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
546   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
547     {
548       const MEDCouplingCartesianAMRPatch *patch(*it);
549       if(patch)
550         {
551           MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
552           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
553           cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
554         }
555     }
556   return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
557 }
558
559 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
560                                                          const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
561 {
562   _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
563 }
564
565 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingCartesianAMRMesh *father, MEDCouplingIMesh *mesh):_father(father)
566 {
567   if(!_father)
568     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh) constructor : empty father !");
569   if(!mesh)
570     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
571   mesh->checkCoherency();
572   _mesh=mesh; _mesh->incrRef();
573 }
574
575 void MEDCouplingCartesianAMRMesh::checkPatchId(int patchId) const
576 {
577   int sz(getNumberOfPatches());
578   if(patchId<0 || patchId>=sz)
579     {
580       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
581       throw INTERP_KERNEL::Exception(oss.str().c_str());
582     }
583 }
584
585 std::size_t MEDCouplingCartesianAMRMesh::getHeapMemorySizeWithoutChildren() const
586 {
587   return sizeof(MEDCouplingCartesianAMRMesh);
588 }
589
590 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
591 {
592   std::vector<const BigMemoryObject *> ret;
593   if((const MEDCouplingIMesh *)_mesh)
594     ret.push_back((const MEDCouplingIMesh *)_mesh);
595   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
596     {
597       if((const MEDCouplingCartesianAMRPatch*)*it)
598         ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
599     }
600   return ret;
601 }
602
603 void MEDCouplingCartesianAMRMesh::updateTime() const
604 {
605   if((const MEDCouplingIMesh *)_mesh)
606     updateTimeWith(*_mesh);
607   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
608     {
609       const MEDCouplingCartesianAMRPatch *elt(*it);
610       if(!elt)
611         continue;
612       const MEDCouplingCartesianAMRMesh *mesh(elt->getMesh());
613       if(mesh)
614         updateTimeWith(*mesh);
615     }
616 }