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