]> SALOME platform Git repositories - modules/med.git/blob - src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx
Salome HOME
Some debugs and improvements. Tests coming soon !
[modules/med.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 "MEDCouplingAMRAttribute.hxx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "MEDCoupling1GTUMesh.hxx"
25 #include "MEDCouplingIMesh.hxx"
26 #include "MEDCouplingUMesh.hxx"
27
28 #include <limits>
29 #include <sstream>
30 #include <numeric>
31
32 using namespace ParaMEDMEM;
33
34 /// @cond INTERNAL
35
36 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithOverlap() const
37 {
38   return _mesh->getNumberOfCellsRecursiveWithOverlap();
39 }
40
41 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithoutOverlap() const
42 {
43   return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
44 }
45
46 int MEDCouplingCartesianAMRPatchGen::getMaxNumberOfLevelsRelativeToThis() const
47 {
48   return _mesh->getMaxNumberOfLevelsRelativeToThis();
49 }
50
51 MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCartesianAMRMeshGen *mesh)
52 {
53   if(!mesh)
54     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen constructor : input mesh is NULL !");
55   _mesh=mesh; _mesh->incrRef();
56 }
57
58 MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(const MEDCouplingCartesianAMRPatchGen& other, MEDCouplingCartesianAMRMeshGen *father):RefCountObject(other),_mesh(other._mesh)
59 {
60   const MEDCouplingCartesianAMRMeshGen *mesh(other._mesh);
61   if(mesh)
62     _mesh=mesh->deepCpy(father);
63 }
64
65 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
66 {
67   const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
68   if(!mesh)
69     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe const : the mesh is NULL !");
70   return mesh;
71 }
72
73 MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
74 {
75   MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
76     if(!mesh)
77       throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe : the mesh is NULL !");
78     return mesh;
79 }
80
81 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildren() const
82 {
83   std::vector<const BigMemoryObject *> ret;
84   if((const MEDCouplingCartesianAMRMeshGen *)_mesh)
85     ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
86   return ret;
87 }
88
89 /*!
90  * \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.
91  * \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,
92  *                                a the end cell (\b excluded) of the range for the second element of the pair.
93  */
94 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight)
95 {
96   int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
97   if(dim!=dimExp)
98     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
99 }
100
101 MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRPatch::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const
102 {
103   return new MEDCouplingCartesianAMRPatch(*this,father);
104 }
105
106 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
107 {
108   return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
109 }
110
111 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
112 {
113   return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
114 }
115
116 /*!
117  * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
118  * the must be >= 0. \b WARNING this method only works if \a this and \a other share the same father (no check of this will be done !).
119  * Call isInMyNeighborhoodExt to deal with 2 patches not sharing directly the same father.
120  *
121  * \param [in] other - The other patch
122  * \param [in] ghostLev - The size of the neighborhood zone.
123  *
124  * \throw if \a this or \a other are invalid (end before start).
125  * \throw if \a ghostLev is \b not >= 0 .
126  * \throw if \a this and \a other have not the same space dimension.
127  *
128  * \sa isInMyNeighborhoodExt
129  */
130 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
131 {
132   if(ghostLev<0)
133     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !");
134   if(!other)
135     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !");
136   const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
137   const std::vector< std::pair<int,int> >& otherp(other->getBLTRRange());
138   return IsInMyNeighborhood(ghostLev,thisp,otherp);
139 }
140
141 /*!
142  * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
143  * the must be >= 0. This method works even if \a this and \a other does not share the same father. But the level between their common
144  * ancestor must be the same. If they don't have the same ancestor an exception will be thrown.
145  *
146  * \param [in] other - The other patch
147  * \param [in] ghostLev - The size of the neighborhood zone.
148  *
149  * \throw if \a this or \a other are invalid (end before start).
150  * \throw if \a ghostLev is \b not >= 0 .
151  * \throw if \a this and \a other have not the same space dimension.
152  * \throw if there is not common ancestor of \a this and \a other.
153  *
154  * \sa isInMyNeighborhood, isInMyNeighborhoodDiffLev
155  */
156 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
157 {
158   if(ghostLev<0)
159     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the size of the neighborhood must be >= 0 !");
160   if(!other)
161     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the input patch is NULL !");
162   int lev;
163   const MEDCouplingCartesianAMRMeshGen *com(FindCommonAncestor(this,other,lev));//check that factors are OK
164   if(lev==0)
165     return isInMyNeighborhood(other,ghostLev);
166   std::vector<int> offset(ComputeOffsetFromTwoToOne(com,lev,this,other));
167   const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
168   std::vector< std::pair<int,int> > otherp(other->getBLTRRange());
169   otherp=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp,offset);
170   return IsInMyNeighborhood(ghostLev,thisp,otherp);
171 }
172
173 /*!
174  * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
175  * the must be >= 0. This method works even if \a this and \a other does not share the same father.
176  * \a this is expected to be more refined than \a other. That is to say lev of \a this is greater than level of \a other.
177  *
178  * \param [in] other - The other patch
179  * \param [in] ghostLev - The size of the neighborhood zone.
180  *
181  * \throw if \a this or \a other are invalid (end before start).
182  * \throw if \a ghostLev is \b not >= 0 .
183  * \throw if \a this and \a other have not the same space dimension.
184  * \throw if there is not common ancestor of \a this and \a other.
185  *
186  * \sa isInMyNeighborhoodExt
187  */
188 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
189 {
190   std::vector< std::pair<int,int> > thispp,otherpp;
191   std::vector<int> factors;
192   ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,this,other,thispp,otherpp,factors);
193   return IsInMyNeighborhood(ghostLev>0?1:0,thispp,otherpp);//1 not ghostLev ! It is not a bug ( I hope :) ) ! Because as \a this is a refinement of \a other ghostLev is supposed to be <= factors
194 }
195
196 std::vector<int> MEDCouplingCartesianAMRPatch::computeCellGridSt() const
197 {
198   const MEDCouplingCartesianAMRMeshGen *m(getMesh());
199   if(!m)
200     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no mesh held by this !");
201   const MEDCouplingCartesianAMRMeshGen *father(m->getFather());
202   if(!father)
203     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no father help by underlying mesh !");
204   const std::vector< std::pair<int,int> >& bltr(getBLTRRange());
205   const std::vector<int>& factors(father->getFactors());
206   std::vector<int> ret(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(bltr));
207   std::transform(ret.begin(),ret.end(),factors.begin(),ret.begin(),std::multiplies<int>());
208   return ret;
209 }
210
211 bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::vector< std::pair<int,int> >& p1, const std::vector< std::pair<int,int> >& p2)
212 {
213   std::size_t thispsize(p1.size());
214   if(thispsize!=p2.size())
215     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !");
216   for(std::size_t i=0;i<thispsize;i++)
217     {
218       const std::pair<int,int>& thispp(p1[i]);
219       const std::pair<int,int>& otherpp(p2[i]);
220       if(thispp.second<thispp.first)
221         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
222       if(otherpp.second<otherpp.first)
223         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
224       if(otherpp.first==thispp.second+ghostLev-1)
225         continue;
226       if(otherpp.second+ghostLev-1==thispp.first)
227         continue;
228       int start(std::max(thispp.first,otherpp.first)),end(std::min(thispp.second,otherpp.second));
229       if(end<start)
230         return false;
231     }
232   return true;
233 }
234
235 /*!
236  * \sa FindNeighborsOfSubPatchesOf
237  */
238 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
239 {
240   if(!p1 || !p2)
241     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev : the input pointers must be not NULL !");
242   std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > ret;
243   std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()),p2Work(p2->getMesh()->getPatches());
244   while(!p1Work.empty())
245     {
246       std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > retTmp;
247       std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2,p2Work2;
248       for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it1=p1Work.begin();it1!=p1Work.end();it1++)
249         {
250           for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
251             {
252               if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev>0?1:0))//1 not ghostLev ! It is not a bug ( I hope :) ) ! Because as \a this is a refinement of \a other ghostLev is supposed to be <= factors
253                 retTmp.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it1,*it2));
254             }
255           std::vector<const MEDCouplingCartesianAMRPatch *> tmp1((*it1)->getMesh()->getPatches());
256           p1Work2.insert(p1Work2.end(),tmp1.begin(),tmp1.end());
257         }
258       for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
259         {
260           std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it2)->getMesh()->getPatches());
261           p2Work2.insert(p2Work2.end(),tmp2.begin(),tmp2.end());
262         }
263       ret.push_back(retTmp);
264       p1Work=p1Work2;
265       p2Work=p2Work2;
266     }
267   return ret;
268 }
269
270 /*!
271  * This method returns all pair of patches (pa,pb) so that pb is in the neighborhood of pa (size of neighborhood is \a ghostLev).
272  * pa is a refinement (a child) of \b p1 and pb is equal to \a p2. So the returned pair do not have the same level as it is the case for
273  * FindNeighborsOfSubPatchesOfSameLev.
274  *
275  * \sa FindNeighborsOfSubPatchesOfSameLev
276  */
277 void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<const MEDCouplingCartesianAMRPatch *, const MEDCouplingCartesianAMRPatch *> >& ret)
278 {
279   if(!p1 || !p2)
280     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf : the input pointers must be not NULL !");
281   std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches());
282   while(!p1Work.empty())
283     {
284       std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2;
285       for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it0=p1Work.begin();it0!=p1Work.end();it0++)
286         {
287           if((*it0)->isInMyNeighborhoodDiffLev(p2,ghostLev))
288             ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it0,p2));
289           std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it0)->getMesh()->getPatches());
290           p1Work2.insert(p1Work2.end(),tmp2.begin(),tmp2.end());
291         }
292       p1Work=p1Work2;
293     }
294 }
295
296 /*!
297  * \a p1 and \a p2 are expected to be neighbors (inside the \a ghostLev zone). This method updates \a dataOnP1 only in the ghost part using a part of \a dataOnP2.
298  *
299  * \saUpdateNeighborsOfOneWithTwoExt
300  */
301 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int ghostLev, const std::vector<int>& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
302 {
303   const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());
304   const std::vector< std::pair<int,int> >& p2BLTR(p2->getBLTRRange());
305   UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2);
306 }
307
308 /*!
309  * Idem than UpdateNeighborsOfOneWithTwo, except that here \a p1 and \a p2 are not sharing the same direct father.
310  *
311  * \sa UpdateNeighborsOfOneWithTwo
312  */
313 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
314 {
315   const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)]
316   std::vector< std::pair<int,int> > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)]
317   int lev(0);
318   const MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev));
319   std::vector<int> offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4]
320   p2BLTR=MEDCouplingStructuredMesh::TranslateCompactFrmt(p2BLTR,offset);//p2BLTR=[(12,13),(4,9)]
321   UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1BLTR,p2BLTR,dataOnP1,dataOnP2);
322 }
323
324 /*!
325  * \a p1 is expected to be more refined than \a p2. \a p1 and \a p2 have to share a common ancestor. Compared to UpdateNeighborsOfOneWithTwoExt here \a p1 and \a p2 are \b not at the same level !
326  */
327 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
328 {
329   std::vector< std::pair<int,int> > p1pp,p2pp;
330   std::vector<int> factors;
331   ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,p1,p2,p1pp,p2pp,factors);
332   //
333   std::vector<int> dimsP2NotRefined(p2->computeCellGridSt());
334   std::vector<int> dimsP2Refined(dimsP2NotRefined);
335   std::transform(dimsP2NotRefined.begin(),dimsP2NotRefined.end(),factors.begin(),dimsP2Refined.begin(),std::multiplies<int>());
336   std::vector< std::pair<int,int> > p2RefinedAbs(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsP2NotRefined));
337   std::vector<int> dimsP2RefinedGhost(dimsP2Refined.size());
338   std::transform(dimsP2Refined.begin(),dimsP2Refined.end(),dimsP2RefinedGhost.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));
339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents());
340   MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev);
341   //
342   UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1pp,p2pp,dataOnP1,fineP2);
343 }
344
345 /*!
346  * \a p1 is expected to be more refined than \a p2. \a p1 and \a p2 have to share a common ancestor. Compared to UpdateNeighborsOfOneWithTwoExt here \a p1 and \a p2 are \b not at the same level !
347  * This method has 3 outputs. 2 two first are the resp the position of \a p1 and \a p2 relative to \a p1. And \a factToApplyOn2 is the coeff of refinement to be applied on \a p2 to be virtualy
348  * on the same level as \a p1.
349  */
350 void MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<int,int> >& p1Zone, std::vector< std::pair<int,int> >& p2Zone, std::vector<int>& factToApplyOn2)
351 {
352   std::vector<const MEDCouplingCartesianAMRMeshGen *> ancestorsOfThis;
353   const MEDCouplingCartesianAMRMeshGen *work(p1->getMesh()),*work2(0);
354   ancestorsOfThis.push_back(work);
355   while(work)
356     {
357       work=work->getFather();
358       if(work)
359         ancestorsOfThis.push_back(work);
360     }
361   //
362   work=p2->getMesh();
363   bool found(false);
364   std::size_t levThis(0),levOther(0);
365   while(work && !found)
366     {
367       work2=work;
368       work=work->getFather();
369       if(work)
370         {
371           levOther++;
372           std::vector<const MEDCouplingCartesianAMRMeshGen *>::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work));
373           if(it!=ancestorsOfThis.end())
374             {
375               levThis=std::distance(ancestorsOfThis.begin(),it);
376               found=true;
377             }
378         }
379     }
380   if(!found)
381     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : no common ancestor found !");
382   if(levThis<=levOther)
383     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : this method is not called correctly !");
384   //
385   const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]);
386   int idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2));
387   const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther));
388   std::vector<int> offset(ComputeOffsetFromTwoToOne(comAncestor,levOther,thisp,otherp));
389   p1Zone=thisp->getBLTRRange(); p2Zone=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset);
390   factToApplyOn2.resize(p1Zone.size()); std::fill(factToApplyOn2.begin(),factToApplyOn2.end(),1);
391   //
392   std::size_t nbOfTurn(levThis-levOther);
393   for(std::size_t i=0;i<nbOfTurn;i++)
394     {
395       std::vector< std::pair<int,int> > tmp0;
396       MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1Zone,p2Zone,tmp0,false);
397       p2Zone=tmp0;
398       const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]);
399       ApplyFactorsOnCompactFrmt(p2Zone,curAncestor->getFactors());
400       curAncestor=ancestorsOfThis[levThis-1-i];
401       const std::vector<int>& factors(curAncestor->getFactors());
402       std::transform(factToApplyOn2.begin(),factToApplyOn2.end(),factors.begin(),factToApplyOn2.begin(),std::multiplies<int>());
403       int tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i]));
404       p1Zone=curAncestor->getPatch(tmpId)->getBLTRRange();
405     }
406 }
407
408 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
409 {
410   std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
411   ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
412   return ret;
413 }
414
415 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, int& lev)
416 {
417   const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
418   lev=0;
419   while(f1!=f2 || f1==0 || f2==0)
420     {
421       f1=f1->getFather(); f2=f2->getFather();
422       if(f1->getFactors()!=f2->getFactors())
423         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : factors differ !");
424       lev++;
425     }
426   if(f1!=f2)
427     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : no common ancestor between p1 and p2 !");
428   return f1;
429 }
430
431 std::vector<int> MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, int lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
432 {
433   if(lev<=0)
434     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : this method is useful only for lev > 0 !");
435   int zeLev(lev-1);
436   int dim(p1->getMesh()->getSpaceDimension());
437   if(p2->getMesh()->getSpaceDimension()!=dim)
438     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : dimension must be the same !");
439   std::vector< int > ret(dim,0);
440   for(int i=0;i<zeLev;i++)
441     {
442       const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
443       const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0);
444       for(int j=0;j<lev-i;j++)
445         {
446           const MEDCouplingCartesianAMRMeshGen *f1tmp(f1->getFather()),*f2tmp(f2->getFather());
447           int pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2));
448           p1h=f1tmp->getPatch(pid1); p2h=f2tmp->getPatch(pid2);
449           f1=f1tmp; f2=f2tmp;
450         }
451       std::vector< std::pair<int,int> > p2c(p2h->getBLTRRange());
452       for(int k=0;k<dim;k++)
453         {
454           p2c[k].first+=ret[k];
455           p2c[k].second+=ret[k];
456         }
457       for(int k=0;k<dim;k++)
458         {
459           ret[k]=p2c[k].first-p1h->getBLTRRange()[k].first;
460           ret[k]*=f1->getFactors()[k];
461         }
462     }
463   return ret;
464 }
465
466 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghostLev, const std::vector<int>& factors, const std::vector< std::pair<int,int> >&p1 ,const std::vector< std::pair<int,int> >&p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
467 {//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)]
468   int dim((int)factors.size());
469   std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2]
470   std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
471   std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
472   std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
473   std::vector<int> fakeFactors(dim,1);
474   //
475   std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
476   MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)]
477   ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)]
478   MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
479   std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
480   MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)]
481   ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)]
482   MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
483   //
484   std::vector< std::pair<int,int> > dimsFine(p2);
485   ApplyFactorsOnCompactFrmt(dimsFine,factors);
486   ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
487   //
488   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
489   MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1);
490 }
491
492 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(const MEDCouplingCartesianAMRPatch& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father),_bl_tr(other._bl_tr)
493 {
494 }
495
496 /*!
497  * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
498  * \param [in] factors - the factors per axis.
499  */
500 void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
501 {
502   std::size_t sz(factors.size());
503   if(sz!=partBeforeFact.size())
504     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
505   for(std::size_t i=0;i<sz;i++)
506     {
507       partBeforeFact[i].first*=factors[i];
508       partBeforeFact[i].second*=factors[i];
509     }
510 }
511
512 /*!
513  * This method is different than ApplyGhostOnCompactFrmt. The \a partBeforeFact parameter is enlarger contrary to ApplyGhostOnCompactFrmt.
514  *
515  * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
516  * \param [in] ghostSize - the ghost size of zone for all axis.
517  */
518 void MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
519 {
520   if(ghostSize<0)
521     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
522   std::size_t sz(partBeforeFact.size());
523   for(std::size_t i=0;i<sz;i++)
524     {
525       partBeforeFact[i].first-=ghostSize;
526       partBeforeFact[i].second+=ghostSize;
527     }
528 }
529
530 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
531 {
532 }
533
534 MEDCouplingCartesianAMRPatchGF *MEDCouplingCartesianAMRPatchGF::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const
535 {
536   return new MEDCouplingCartesianAMRPatchGF(*this,father);
537 }
538
539 std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
540 {
541   return sizeof(MEDCouplingCartesianAMRPatchGF);
542 }
543
544 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father)
545 {
546 }
547
548 /// @endcond
549
550 int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const
551 {
552   return _mesh->getSpaceDimension();
553 }
554
555 void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFactors)
556 {
557   if(getSpaceDimension()!=(int)newFactors.size())
558     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : size of input factors is not equal to the space dimension !");
559   if(_factors.empty())
560     {
561       _factors=newFactors;
562       return ;
563     }
564   if(_factors==newFactors)
565     return ;
566   if(!_patches.empty())
567     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : modification of factors is not allowed when presence of patches !");
568   _factors=newFactors;
569   declareAsNew();
570 }
571
572 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
573 {
574   int ret(1);
575   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
576     ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
577   return ret;
578 }
579
580 /*!
581  * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this.
582  * The patches in \a this are ignored here.
583  * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap
584  */
585 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
586 {
587   return _mesh->getNumberOfCells();
588 }
589
590 /*!
591  * 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
592  * to take into account of the ghost cells for future computation.
593  * The patches in \a this are ignored here.
594  *
595  * \sa getNumberOfCellsAtCurrentLevel
596  */
597 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
598 {
599   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
600   return tmp->getNumberOfCells();
601 }
602
603 /*!
604  * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels
605  * starting from this. The set of cells which size is returned here are generally overlapping each other.
606  */
607 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
608 {
609   int ret(_mesh->getNumberOfCells());
610   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
611     {
612       ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
613     }
614   return ret;
615 }
616
617 /*!
618  * This method returns the max number of cells covering all the space without overlapping.
619  * It returns the number of cells of the mesh with the highest resolution.
620  * The returned value is equal to the number of cells of mesh returned by buildUnstructured.
621  *
622  * \sa buildUnstructured
623  */
624 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
625 {
626   int ret(_mesh->getNumberOfCells());
627   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
628     {
629       ret-=(*it)->getNumberOfOverlapedCellsForFather();
630       ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
631     }
632   return ret;
633 }
634
635 /*!
636  * This method returns a vector of size equal to getAbsoluteLevelRelativeTo. It allows to find position an absolute position of \a this
637  * relative to \a ref (that is typically the god father).
638  *
639  * \sa getPatchAtPosition
640  */
641 std::vector<int> MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
642 {
643   if(!ref)
644     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo : input pointer is NULL !");
645   std::vector<int> ret;
646   getPositionRelativeToInternal(ref,ret);
647   std::reverse(ret.begin(),ret.end());
648   return ret;
649 }
650
651 /*!
652  * \sa getPositionRelativeTo, getMeshAtPosition
653  */
654 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatchAtPosition(const std::vector<int>& pos) const
655 {
656   std::size_t sz(pos.size());
657   if(sz==0)
658     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : empty input -> no patch by definition !");
659   int patchId(pos[0]);
660   const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId));
661   if(sz==1)
662     return elt;
663   if(!elt || !elt->getMesh())
664     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !");
665   std::vector<int> pos2(pos.begin()+1,pos.end());
666   return elt->getMesh()->getPatchAtPosition(pos2);
667 }
668
669 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getMeshAtPosition(const std::vector<int>& pos) const
670 {
671   std::size_t sz(pos.size());
672   if(sz==0)
673     return this;
674   int patchId(pos[0]);
675   const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId));
676   if(sz==1)
677     {
678       if(!elt)
679         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getMeshAtPosition : NULL patch !");
680       return elt->getMesh();
681     }
682   if(!elt || !elt->getMesh())
683     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !");
684   std::vector<int> pos2(pos.begin()+1,pos.end());
685   return elt->getMesh()->getMeshAtPosition(pos2);
686 }
687
688 /*!
689  * This method returns grids relative to god father to specified level \a absoluteLev.
690  *
691  * \return std::vector<MEDCouplingCartesianAMRPatchGen *> - objects in vector are to be managed (decrRef) by the caller.
692  */
693 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(int absoluteLev) const
694 {
695   if(absoluteLev<0)
696     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !");
697   return getGodFather()->retrieveGridsAt(absoluteLev);
698 }
699
700 /*!
701  * \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,
702  *                                a the end cell (\b excluded) of the range for the second element of the pair.
703  * \param [in] factors The factor of refinement per axis (different from 0).
704  */
705 void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
706 {
707   checkFactorsAndIfNotSetAssign(factors);
708   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
709   mesh->refineWithFactor(factors);
710   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
711   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
712   _patches.push_back(elt);
713   declareAsNew();
714 }
715
716 /// @cond INTERNAL
717
718 class InternalPatch : public RefCountObjectOnly
719 {
720 public:
721   InternalPatch():_nb_of_true(0) { }
722   int getDimension() const { return (int)_part.size(); }
723   double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
724   int getNumberOfCells() const { return (int)_crit.size(); }
725   void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
726   std::vector<bool>& getCriterion() { return _crit; }
727   const std::vector<bool>& getConstCriterion() const { return _crit; }
728   void setPart(const std::vector< std::pair<int,int> >& part) { _part=part; }
729   std::vector< std::pair<int,int> >& getPart() { return _part; }
730   const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
731   bool presenceOfTrue() const { return _nb_of_true>0; }
732   std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
733   std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
734   double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
735   void zipToFitOnCriterion();
736   void updateNumberOfTrue() const;
737   MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
738   MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
739 protected:
740   ~InternalPatch() { }
741 private:
742   mutable int _nb_of_true;
743   std::vector<bool> _crit;
744   //! _part is global
745   std::vector< std::pair<int,int> > _part;
746 };
747
748 void InternalPatch::zipToFitOnCriterion()
749 {
750   std::vector<int> cgs(computeCGS());
751   std::vector<bool> newCrit;
752   std::vector< std::pair<int,int> > newPart,newPart2;
753   int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart));
754   MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
755   if(newNbOfTrue!=_nb_of_true)
756     throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
757   _crit=newCrit; _part=newPart2;
758 }
759
760 void InternalPatch::updateNumberOfTrue() const
761 {
762   _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
763 }
764
765 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
766 {
767   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
768   std::vector<int> cgs(computeCGS());
769   std::vector< std::pair<int,int> > newPart;
770   MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
771   MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion());
772   ret->setPart(partInGlobal);
773   ret->updateNumberOfTrue();
774   return ret;
775 }
776
777 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
778 {
779   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
780   (*ret)=*this;
781   return ret;
782 }
783
784 void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
785 {
786   cutFound=false; cutPlace=-1;
787   std::vector<double> ratio(rangeOfAxisId-1);
788   for(int id=0;id<rangeOfAxisId-1;id++)
789     {
790       double efficiency[2];
791       for(int h=0;h<2;h++)
792         {
793           std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
794           if(h==0)
795             rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id;
796           else
797             rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id;
798           MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
799           p->zipToFitOnCriterion();
800           //anouar rectH ?
801           efficiency[h]=p->getEfficiencyPerAxis(axisId);
802         }
803       ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]);
804     }
805   int minCellDirection(bso.getMinCellDirection()),indexMin(-1);
806   int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1));
807   std::vector<double> ratio_inner(dimRatioInner);
808   double minRatio(1.e10);
809   for(int i=0; i<dimRatioInner; i++)
810     {
811       if(ratio[minCellDirection-1+i]<minRatio)
812         {
813           minRatio=ratio[minCellDirection-1+i];
814           indexMin=i+minCellDirection;
815         }
816     }
817   cutFound=true; cutPlace=indexMin+patchToBeSplit->getConstPart()[axisId].first-1;
818 }
819
820 void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace)
821 {
822   cutPlace=-1; cutFound=false;
823   int minCellDirection(bso.getMinCellDirection());
824   const int dim(patchToBeSplit->getDimension());
825   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
826   for(int id=0;id<dim;id++)
827     {
828       const std::vector<int>& signature(signatures[id]);
829       std::vector<int> hole;
830       std::vector<double> distance;
831       int len((int)signature.size());
832       for(int i=0;i<len;i++)
833         if(signature[i]==0)
834           if(len>= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1)
835             hole.push_back(i);
836       if(!hole.empty())
837         {
838           double center(((double)len/2.));
839           for(std::size_t i=0;i<hole.size();i++)
840             distance.push_back(fabs(hole[i]+1.-center));
841
842           std::size_t posDistanceMin(std::distance(distance.begin(),std::min_element(distance.begin(),distance.end())));
843           cutFound=true;
844           axisId=id;
845           cutPlace=hole[posDistanceMin]+patchToBeSplit->getConstPart()[axisId].first+1;
846           return ;
847         }
848     }
849 }
850
851 void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId)
852 {
853   cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
854
855   const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
856   int sign,minCellDirection(bso.getMinCellDirection());
857   const int dim(patchToBeSplit->getDimension());
858
859   std::vector<int> zeroCrossDims(dim,-1);
860   std::vector<int> zeroCrossVals(dim,-1);
861   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
862   for (int id=0;id<dim;id++)
863     {
864       const std::vector<int>& signature(signatures[id]);
865
866       std::vector<int> derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ;
867       std::vector<double> distance ;
868
869       for (unsigned int i=1;i<signature.size()-1;i++)
870         derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
871
872       // Gradient absolute value
873       for ( unsigned int i=1;i<derivate_second_order.size();i++)
874         gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
875       if(derivate_second_order.empty())
876         continue;
877       for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
878         {
879           if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
880             sign = -1 ;
881           if (derivate_second_order[i]*derivate_second_order[i+1] > 0 )
882             sign = 1 ;
883           if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
884             sign = 0 ;
885           if ( sign==0 || sign==-1 )
886             if ( i >= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 )
887               {
888                 zero_cross.push_back(i) ;
889                 edge.push_back(gradient_absolute[i]) ;
890               }
891           signe_change.push_back(sign) ;
892         }
893       if ( zero_cross.size() > 0 )
894         {
895           int max_cross=*max_element(edge.begin(),edge.end()) ;
896           for (unsigned int i=0;i<edge.size();i++)
897             if (edge[i]==max_cross)
898               max_cross_list.push_back(zero_cross[i]+1) ;
899
900           double center((signature.size()/2.0));
901           for (unsigned int i=0;i<max_cross_list.size();i++)
902             distance.push_back(fabs(max_cross_list[i]+1-center));
903
904           float distance_min=*min_element(distance.begin(),distance.end()) ;
905           int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
906           int best_place = max_cross_list[pos_distance_min] + part[id].first ;
907           if ( max_cross >=0 )
908             {
909               zeroCrossDims[id] = best_place ;
910               zeroCrossVals[id] = max_cross ;
911             }
912         }
913       derivate_second_order.clear() ;
914       gradient_absolute.clear() ;
915       signe_change.clear() ;
916       zero_cross.clear() ;
917       edge.clear() ;
918       max_cross_list.clear() ;
919       distance.clear() ;
920     }
921
922   if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1  )
923     {
924       int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ;
925
926       if (zeroCrossVals[0]==max_cross_dims &&  zeroCrossVals[1]==max_cross_dims )
927         {
928           int nl_left(part[0].second-part[0].first);
929           int nc_left(part[1].second-part[1].first);
930           if ( nl_left >=  nc_left )
931             max_cross_dims = 0 ;
932           else
933             max_cross_dims = 1 ;
934         }
935       else
936         max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin();
937       cutFound=true;
938       cutPlace=zeroCrossDims[max_cross_dims];
939       axisId=max_cross_dims ;
940     }
941 }
942
943 void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
944 {
945   cutFound=false;
946   if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd())
947     {
948       if(rangeOfAxisId>=2*bso.getMinCellDirection())
949         {
950           cutFound=true;
951           cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
952         }
953     }
954   else
955     {
956       if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells())
957         {
958           DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace);
959         }
960     }
961 }
962
963 MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
964 {
965   MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
966   ret->incrRef();
967   return ret;
968 }
969
970 void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
971 {
972   MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
973   std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
974   std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
975   leftRect[axisId].second=cutPlace+1;
976   rightRect[axisId].first=cutPlace+1;
977   leftPart=patchToBeSplit->extractPart(leftRect);
978   rightPart=patchToBeSplit->extractPart(rightRect);
979   leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion();
980   listOfPatches.push_back(leftPart);
981   listOfPatches.push_back(rightPart);
982 }
983
984 /// @endcond
985
986 void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
987 {
988   _patches.clear();
989   declareAsNew();
990 }
991
992 void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
993 {
994   checkPatchId(patchId);
995   int sz((int)_patches.size()),j(0);
996   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
997   for(int i=0;i<sz;i++)
998     if(i!=patchId)
999       patches[j++]=_patches[i];
1000   (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
1001   _patches=patches;
1002   declareAsNew();
1003 }
1004
1005 int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
1006 {
1007   return (int)_patches.size();
1008 }
1009
1010 /*!
1011  * 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.
1012  * This method only create patches at level 0 relative to \a this.
1013  */
1014 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
1015 {
1016   int nbCells(getNumberOfCellsAtCurrentLevel());
1017   if(nbCells!=(int)criterion.size())
1018     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
1019   _patches.clear();
1020   std::vector<int> cgs(_mesh->getCellGridStructure());
1021   std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
1022   //
1023   MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
1024   p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart()));
1025   if(p->presenceOfTrue())
1026     listOfPatches.push_back(p);
1027   while(!listOfPatches.empty())
1028     {
1029       std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
1030       for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
1031         {
1032           //
1033           int axisId,rangeOfAxisId,cutPlace;
1034           bool cutFound;
1035           MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId);
1036           if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()<bso.getMaxCells())
1037             { listOfPatchesOK.push_back(DealWithNoCut(*it)); continue; }//action 1
1038           FindHole(bso,*it,axisId,cutFound,cutPlace);//axisId overwritten here if FindHole equal to true !
1039           if(cutFound)
1040             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
1041           FindInflection(bso,*it,cutFound,cutPlace,axisId);//axisId overwritten here if cutFound equal to true !
1042           if(cutFound)
1043             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
1044           TryAction4(bso,*it,axisId,rangeOfAxisId,cutFound,cutPlace);
1045           if(cutFound)
1046             { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
1047           listOfPatchesOK.push_back(DealWithNoCut(*it));
1048         }
1049       listOfPatches=listOfPatchesTmp;
1050     }
1051   for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
1052     addPatch((*it)->getConstPart(),factors);
1053   declareAsNew();
1054 }
1055
1056 /*!
1057  * 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.
1058  * This method only create patches at level 0 relative to \a this.
1059  */
1060 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
1061 {
1062   if(!criterion || !criterion->isAllocated())
1063     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
1064   std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
1065   createPatchesFromCriterion(bso,crit,factors);
1066   declareAsNew();
1067 }
1068
1069 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayDouble *criterion, const std::vector<int>& factors, double eps)
1070 {
1071   if(!criterion)
1072     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : null criterion pointer !");
1073   std::vector<bool> inp(criterion->toVectorOfBool(eps));
1074   createPatchesFromCriterion(bso,inp,factors);
1075 }
1076
1077 int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
1078 {
1079   int ret(0);
1080   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
1081     {
1082       if((*it)->getMesh()==mesh)
1083         return ret;
1084     }
1085   throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
1086 }
1087
1088 std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
1089 {
1090   std::size_t sz(_patches.size());
1091   std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
1092   for(std::size_t i=0;i<sz;i++)
1093     ret[i]=_patches[i];
1094   return ret;
1095 }
1096
1097 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const
1098 {
1099   checkPatchId(patchId);
1100   return _patches[patchId];
1101 }
1102
1103 /*!
1104  * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1).
1105  * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !).
1106  */
1107 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
1108 {
1109   const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
1110   return p1->isInMyNeighborhood(p2,ghostLev);
1111 }
1112
1113 /*!
1114  * 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.
1115  * 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
1116  * defined by the patch with id \a patchId.
1117  *
1118  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1119  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1120  * \return DataArrayDouble * - The array of the cell field on the requested patch
1121  *
1122  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1123  * \throw if \a cellFieldOnThis is NULL or not allocated
1124  * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine
1125  */
1126 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const
1127 {
1128   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1129     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1130   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1131   const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
1132   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
1133   ret->copyStringInfoFrom(*cellFieldOnThis);
1134   MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
1135   return ret.retn();
1136 }
1137
1138 /*!
1139  * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of creating a new instance
1140  * it fills the value into the \a cellFieldOnPatch data.
1141  *
1142  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1143  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1144  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1145  *
1146  * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
1147  */
1148 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, bool isConservative) const
1149 {
1150   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1151     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1152   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1153   MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
1154   if(isConservative)
1155     {
1156       int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1157       std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
1158     }
1159 }
1160
1161 /*!
1162  * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the
1163  * potential neighbor patches covered by the ghost cells of patch with id \a patchId.
1164  *
1165  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1166  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1167  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1168  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1169  *
1170  * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
1171  */
1172 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev, bool isConservative) const
1173 {
1174   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1175     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
1176   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1177   MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1178   if(isConservative)
1179     {
1180       int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1181       std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
1182     }
1183 }
1184
1185 /*!
1186  * This method is equivalent to  fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
1187  * in \a cellFieldOnPatch.
1188  *
1189  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1190  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1191  * \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.
1192  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1193  */
1194 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
1195 {
1196   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1197     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
1198   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1199   MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1200 }
1201
1202 /*!
1203  * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
1204  * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
1205  *
1206  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1207  * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1208  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1209  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1210  * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
1211  *
1212  * \sa fillCellFieldOnPatchOnlyGhostAdv
1213  */
1214 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches, bool isConservative) const
1215 {
1216   int nbp(getNumberOfPatches());
1217   if(nbp!=(int)arrsOnPatches.size())
1218     {
1219       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1220       throw INTERP_KERNEL::Exception(oss.str().c_str());
1221     }
1222   DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1223   // first, do as usual
1224   fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev,isConservative);
1225   fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
1226 }
1227
1228 /*!
1229  * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
1230  * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
1231  *
1232  * \sa getPatchIdsInTheNeighborhoodOf
1233  */
1234 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
1235 {
1236   int nbp(getNumberOfPatches());
1237   if(nbp!=(int)arrsOnPatches.size())
1238     {
1239       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1240       throw INTERP_KERNEL::Exception(oss.str().c_str());
1241     }
1242   const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
1243   DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1244   std::vector<int> ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
1245   for(std::vector<int>::const_iterator it=ids.begin();it!=ids.end();it++)
1246     {
1247       const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it));
1248       MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]);
1249     }
1250 }
1251
1252 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const
1253 {
1254   MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor);
1255 }
1256
1257 /*!
1258  * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
1259  *
1260  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1261  * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1262  * \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.
1263  * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
1264  *
1265  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1266  * \throw if \a cellFieldOnPatch is NULL or not allocated
1267  * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
1268  */
1269 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, bool isConservative) const
1270 {
1271   if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1272       throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
1273   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1274   MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
1275   if(!isConservative)
1276     {
1277       int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1278       MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis);
1279     }
1280 }
1281
1282 /*!
1283  * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this
1284  * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch.
1285  *
1286  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1287  * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1288  * \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.
1289  * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
1290  * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
1291  *
1292  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1293  * \throw if \a cellFieldOnPatch is NULL or not allocated
1294  * \sa fillCellFieldComingFromPatch
1295  */
1296 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev, bool isConservative) const
1297 {
1298   if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1299     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
1300   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1301   MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
1302   if(!isConservative)
1303     {
1304       int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1305       MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis);
1306     }
1307 }
1308
1309 /*!
1310  * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is
1311  * defined by ghostLev.
1312  *
1313  * \param [in] patchId - the id of the considered patch.
1314  * \param [in] ghostLev - the size of the neighborhood.
1315  * \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.
1316  */
1317 DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const
1318 {
1319   int nbp(getNumberOfPatches());
1320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1321   for(int i=0;i<nbp;i++)
1322     {
1323       if(i!=patchId)
1324         if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1325           ret->pushBackSilent(i);
1326     }
1327   return ret.retn();
1328 }
1329
1330 MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
1331 {
1332   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1333   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1334   std::vector<int> cgs(_mesh->getCellGridStructure());
1335   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
1336   std::size_t ii(0);
1337   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1338     {
1339       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1340       msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
1341     }
1342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1343   msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1344   std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
1345   for(std::size_t i=0;i<msSafe.size();i++)
1346     ms[i]=msSafe[i];
1347   return MEDCouplingUMesh::MergeUMeshes(ms);
1348 }
1349
1350 /*!
1351  * This method returns a mesh containing as cells that there is patches at the current level.
1352  * The patches are seen like 'boxes' that is too say the refinement will not appear here.
1353  *
1354  * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
1355  */
1356 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
1357 {
1358   std::vector<const MEDCoupling1SGTUMesh *> cells;
1359   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
1360   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1361     {
1362       const MEDCouplingCartesianAMRPatch *patch(*it);
1363       if(patch)
1364         {
1365           MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
1366           MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
1367           cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
1368         }
1369     }
1370   return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
1371 }
1372
1373 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
1374 {
1375   std::vector<const MEDCoupling1SGTUMesh *> patches;
1376   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > patchesSafe;
1377   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1378       {
1379         const MEDCouplingCartesianAMRPatch *patch(*it);
1380         if(patch)
1381           {
1382             MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
1383             patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
1384           }
1385       }
1386     return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
1387 }
1388
1389 /*!
1390  * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
1391  * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
1392  * \sa buildUnstructured
1393  */
1394 MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
1395 {
1396   if(recurseArrs.empty())
1397     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
1398   //
1399   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1400   std::vector<int> cgs(_mesh->getCellGridStructure());
1401   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
1402   std::size_t ii(0);
1403   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1404     {
1405       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1406       std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
1407       msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
1408     }
1409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1410   //
1411   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
1412   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
1413   arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
1414   ret->setArray(arr2);
1415   ret->setName(arr2->getName());
1416   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1417   MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1418   ret->setMesh(mesh);
1419   msSafe[0]=ret;
1420   //
1421   std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
1422   for(std::size_t i=0;i<msSafe.size();i++)
1423     ms[i]=msSafe[i];
1424   //
1425   return MEDCouplingFieldDouble::MergeFields(ms);
1426 }
1427
1428 /*!
1429  * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
1430  * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
1431  */
1432 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const
1433 {
1434   std::vector<int> st(_mesh->getCellGridStructure());
1435   std::vector< std::pair<int,int> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
1436   std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus<int>(),2*ghostSz));
1437   MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz);
1438   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
1439   return ret.retn();
1440 }
1441
1442 /*!
1443  * This method returns all the patches in \a this not equal to \a patchId that are in neighborhood of patch with id \a patchId.
1444  *
1445  * \sa fillCellFieldOnPatchOnlyGhostAdv
1446  */
1447 std::vector<int> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(int patchId, int ghostLev) const
1448 {
1449   std::vector<int> ret;
1450   int nbp(getNumberOfPatches());
1451   //
1452   for(int i=0;i<nbp;i++)
1453     {
1454       if(i!=patchId)
1455         if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1456           ret.push_back(i);
1457     }
1458   return ret;
1459 }
1460
1461 /*!
1462  * This method returns a dump python of \a this. It is useful for users of createPatchesFromCriterion method for debugging.
1463  *
1464  * \sa dumpPatchesOf, createPatchesFromCriterion, createPatchesFromCriterionML
1465  */
1466 std::string MEDCouplingCartesianAMRMeshGen::buildPythonDumpOfThis() const
1467 {
1468   std::ostringstream oss;
1469   oss << "amr=MEDCouplingCartesianAMRMesh(\""<< getImageMesh()->getName() << "\"," << getSpaceDimension() << ",[";
1470   std::vector<int> ngs(getImageMesh()->getNodeGridStructure());
1471   std::vector<double> orig(getImageMesh()->getOrigin()),dxyz(getImageMesh()->getDXYZ());
1472   std::copy(ngs.begin(),ngs.end(),std::ostream_iterator<int>(oss,","));
1473   oss <<  "],[";
1474   std::copy(orig.begin(),orig.end(),std::ostream_iterator<double>(oss,","));
1475   oss << "],[";
1476   std::copy(dxyz.begin(),dxyz.end(),std::ostream_iterator<double>(oss,","));
1477   oss << "])\n";
1478   dumpPatchesOf("amr",oss);
1479   return oss.str();
1480 }
1481
1482 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const MEDCouplingCartesianAMRMeshGen& other):RefCountObject(other),_mesh(other._mesh),_patches(other._patches),_factors(other._factors)
1483 {
1484   const MEDCouplingIMesh *mesh(other._mesh);
1485   if(mesh)
1486     _mesh=static_cast<MEDCouplingIMesh *>(mesh->deepCpy());
1487   std::size_t sz(other._patches.size());
1488   for(std::size_t i=0;i<sz;i++)
1489     {
1490       const MEDCouplingCartesianAMRPatch *patch(other._patches[i]);
1491       if(patch)
1492         _patches[i]=patch->deepCpy(this);
1493     }
1494 }
1495
1496 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1497                                                                const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1498 {
1499   _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1500 }
1501
1502 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh)
1503 {
1504   if(!mesh)
1505     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
1506   mesh->checkCoherency();
1507   _mesh=mesh; _mesh->incrRef();
1508 }
1509
1510 void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const
1511 {
1512   int sz(getNumberOfPatches());
1513   if(patchId<0 || patchId>=sz)
1514     {
1515       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
1516       throw INTERP_KERNEL::Exception(oss.str().c_str());
1517     }
1518 }
1519
1520 void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector<int>& factors)
1521 {
1522   if(getSpaceDimension()!=(int)factors.size())
1523     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !");
1524   if(_factors.empty())
1525     {
1526       _factors=factors;
1527     }
1528   else
1529     {
1530       if(_factors!=factors)
1531         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : the factors ");
1532     }
1533 }
1534
1535 void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> >& grids) const
1536 {
1537   if(lev==0)
1538     {
1539       const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
1540       MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
1541       grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
1542     }
1543   else if(lev==1)
1544     {
1545       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1546         {
1547           const MEDCouplingCartesianAMRPatch *pt(*it);
1548           if(pt)
1549             {
1550               MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> tmp1(*it);
1551               grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
1552             }
1553         }
1554     }
1555   else
1556     {
1557       for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1558         {
1559           const MEDCouplingCartesianAMRPatch *pt(*it);
1560           if(pt)
1561             pt->getMesh()->retrieveGridsAtInternal(lev-1,grids);
1562         }
1563     }
1564 }
1565
1566 int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const std::vector<int>& factors)
1567 {
1568   if(ghostLev<0)
1569     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !");
1570   if(factors.empty())
1571     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !");
1572   int ghostLevInPatchRef;
1573   if(ghostLev==0)
1574     ghostLevInPatchRef=0;
1575   else
1576     {
1577       ghostLevInPatchRef=(ghostLev-1)/factors[0]+1;
1578       for(std::size_t i=0;i<factors.size();i++)
1579         ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/factors[i]+1);
1580     }
1581   return ghostLevInPatchRef;
1582 }
1583
1584 /*!
1585  * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
1586  * Elements in \a all are expected to be sorted from god father to most refined structure.
1587  */
1588 std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
1589 {
1590   int maxLev(getMaxNumberOfLevelsRelativeToThis());
1591   std::vector<const DataArrayDouble *> ret;
1592   std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
1593   std::size_t kk(0);
1594   for(int i=0;i<maxLev;i++)
1595     {
1596       std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
1597       for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
1598         {
1599           if((*it)==head || head->isObjectInTheProgeny(*it))
1600             ret.push_back(all[kk]);
1601           kk++;
1602           std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
1603           for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
1604             {
1605               const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
1606               meshesTmp.push_back(mesh);
1607             }
1608         }
1609       meshes=meshesTmp;
1610     }
1611   if(kk!=all.size())
1612     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
1613   return ret;
1614 }
1615
1616 void MEDCouplingCartesianAMRMeshGen::dumpPatchesOf(const std::string& varName, std::ostream& oss) const
1617 {
1618   std::size_t j(0);
1619   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1620     {
1621       const MEDCouplingCartesianAMRPatch *patch(*it);
1622       if(patch)
1623         {
1624           std::ostringstream oss2; oss2 << varName << ".addPatch([";
1625           const std::vector< std::pair<int,int> >& bltr(patch->getBLTRRange());
1626           std::size_t sz(bltr.size());
1627           for(std::size_t i=0;i<sz;i++)
1628             {
1629               oss2 << "(" << bltr[i].first << "," << bltr[i].second << ")";
1630               if(i!=sz-1)
1631                 oss2 << ",";
1632             }
1633           oss2 << "],[";
1634           std::copy(_factors.begin(),_factors.end(),std::ostream_iterator<int>(oss2,","));
1635           oss2 << "])\n";
1636           oss << oss2.str();
1637           std::ostringstream oss3; oss3 << varName << "[" << j++ << "]";
1638           patch->getMesh()->dumpPatchesOf(oss3.str(),oss);
1639         }
1640     }
1641 }
1642
1643 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
1644 {
1645   return sizeof(MEDCouplingCartesianAMRMeshGen);
1646 }
1647
1648 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildren() const
1649 {
1650   std::vector<const BigMemoryObject *> ret;
1651   if((const MEDCouplingIMesh *)_mesh)
1652     ret.push_back((const MEDCouplingIMesh *)_mesh);
1653   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1654     {
1655       if((const MEDCouplingCartesianAMRPatch*)*it)
1656         ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
1657     }
1658   return ret;
1659 }
1660
1661 void MEDCouplingCartesianAMRMeshGen::updateTime() const
1662 {
1663   if((const MEDCouplingIMesh *)_mesh)
1664     updateTimeWith(*_mesh);
1665   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1666     {
1667       const MEDCouplingCartesianAMRPatch *elt(*it);
1668       if(!elt)
1669         continue;
1670       const MEDCouplingCartesianAMRMeshGen *mesh(elt->getMesh());
1671       if(mesh)
1672         updateTimeWith(*mesh);
1673     }
1674 }
1675
1676 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh),_father(father)
1677 {
1678   if(!_father)
1679     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh) constructor : empty father !");
1680 }
1681
1682 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getFather() const
1683 {
1684   return _father;
1685 }
1686
1687 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getGodFather() const
1688 {
1689   if(!_father)
1690     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getGodFather : Impossible to find a god father because there is a hole in chain !");
1691   return _father->getGodFather();
1692 }
1693
1694 /*!
1695  * This method returns the level of \a this. 0 for god father. 1 for children of god father ...
1696  */
1697 int MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel() const
1698 {
1699   if(!_father)
1700     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel : Impossible to find a god father because there is a hole in chain !");
1701   return _father->getAbsoluteLevel()+1;
1702 }
1703
1704 void MEDCouplingCartesianAMRMeshSub::detachFromFather()
1705 {
1706   _father=0;
1707   declareAsNew();
1708 }
1709
1710 int MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
1711 {
1712   if(this==ref)
1713     return 0;
1714   if(_father==0)
1715     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
1716   else
1717     return _father->getAbsoluteLevelRelativeTo(ref)+1;
1718 }
1719
1720 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(const MEDCouplingCartesianAMRMeshSub& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRMeshGen(other),_father(father)
1721 {
1722 }
1723
1724 MEDCouplingCartesianAMRMeshSub *MEDCouplingCartesianAMRMeshSub::deepCpy(MEDCouplingCartesianAMRMeshGen *fath) const
1725 {
1726   return new MEDCouplingCartesianAMRMeshSub(*this,fath);
1727 }
1728
1729 /*!
1730  * \sa getPositionRelativeTo
1731  */
1732 void MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<int>& ret) const
1733 {
1734   if(this==ref)
1735     return ;
1736   if(!_father)
1737     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal : ref is not in the progeny of this !");
1738   int myId(_father->getPatchIdFromChildMesh(this));
1739   ret.push_back(myId);
1740   _father->getPositionRelativeToInternal(ref,ret);
1741 }
1742
1743 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1744                                                               const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1745 {
1746   return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1747 }
1748
1749 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getFather() const
1750 {
1751   //I'm god father ! No father !
1752   return 0;
1753 }
1754
1755 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getGodFather() const
1756 {
1757   return this;
1758 }
1759
1760 int MEDCouplingCartesianAMRMesh::getAbsoluteLevel() const
1761 {
1762   return 0;
1763 }
1764
1765 void MEDCouplingCartesianAMRMesh::detachFromFather()
1766 {//not a bug - do nothing
1767 }
1768
1769 int MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
1770 {
1771   if(this==ref)
1772     return 0;
1773   throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
1774 }
1775
1776 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMesh::retrieveGridsAt(int absoluteLev) const
1777 {
1778   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > rets;
1779   retrieveGridsAtInternal(absoluteLev,rets);
1780   std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
1781   for(std::size_t i=0;i<rets.size();i++)
1782     {
1783       ret[i]=rets[i].retn();
1784     }
1785   return ret;
1786 }
1787
1788 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const
1789 {
1790   if(father)
1791     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::deepCpy : specifying a not null father for a God Father object !");
1792   return new MEDCouplingCartesianAMRMesh(*this);
1793 }
1794
1795 /*!
1796  * This method creates a multi level patches split at once.
1797  * This method calls as times as size of \a bso createPatchesFromCriterion. Size of \a bso and size of \a factors must be the same !
1798  * \b WARNING, after the call the number of levels in \a this is equal to bso.size() + 1 !
1799  *
1800  * \param [in] bso
1801  * \param [in] criterion
1802  * \param [in] factors
1803  * \param [in] eps - See DataArrayDouble::toVectorOfBool for more information about the semantic of eps.
1804  *
1805  * \sa createPatchesFromCriterion
1806  */
1807 void MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML(const std::vector<const INTERP_KERNEL::BoxSplittingOptions *>& bso, const DataArrayDouble *criterion, const std::vector< std::vector<int> >& factors, double eps)
1808 {
1809   std::size_t nbOfLevs(bso.size());
1810   if(nbOfLevs!=factors.size())
1811     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : size of vectors must be the same !");
1812   if(nbOfLevs==0)
1813     return ;
1814   if(!bso[0])
1815     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : pointers in 1st arg must be not NULL !");
1816   createPatchesFromCriterion(*bso[0],criterion,factors[0],eps);
1817   for(std::size_t i=1;i<nbOfLevs;i++)
1818     {
1819       if(!bso[i])
1820         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : presence of a NULL BoxSplittingOptions in input vector !");
1821       //
1822       std::vector<MEDCouplingCartesianAMRPatchGen *> elts(retrieveGridsAt((int)(i)));
1823       std::size_t sz(elts.size());
1824       std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > elts2(sz);
1825       std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > elts3(sz);
1826       for(std::size_t ii=0;ii<sz;ii++)
1827         elts2[ii]=elts[ii];
1828       //
1829       static const char TMP_STR[]="TMP";
1830       std::vector< std::pair<std::string,int> > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1;
1831       MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> att(MEDCouplingAMRAttribute::New(this,fieldNames,0));
1832       att->alloc();
1833       DataArrayDouble *tmpDa(const_cast<DataArrayDouble *>(att->getFieldOn(this,TMP_STR)));
1834       tmpDa->cpyFrom(*criterion);
1835       att->synchronizeCoarseToFine();
1836       for(std::size_t ii=0;ii<sz;ii++)
1837         {
1838           const DataArrayDouble *critOnLeaf(att->getFieldOn(const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh()),TMP_STR));
1839           elts3[ii]=const_cast<DataArrayDouble *>(critOnLeaf); elts3[ii]->incrRef();
1840         }
1841       att=0;
1842       for(std::size_t ii=0;ii<sz;ii++)
1843         const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh())->createPatchesFromCriterion(*bso[i],elts3[ii],factors[i],eps);
1844     }
1845 }
1846
1847 void MEDCouplingCartesianAMRMesh::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<int>& ret) const
1848 {
1849
1850 }
1851
1852 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const MEDCouplingCartesianAMRMesh& other):MEDCouplingCartesianAMRMeshGen(other)
1853 {
1854 }
1855
1856 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1857                                                          const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
1858 {
1859 }
1860
1861 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
1862 {
1863   std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren());
1864   return ret;
1865 }
1866
1867 MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()
1868 {
1869 }