1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay
21 #include "MEDCouplingCartesianAMRMesh.hxx"
22 #include "MEDCouplingAMRAttribute.hxx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "MEDCoupling1GTUMesh.hxx"
25 #include "MEDCouplingIMesh.hxx"
26 #include "MEDCouplingUMesh.hxx"
32 using namespace ParaMEDMEM;
36 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithOverlap() const
38 return _mesh->getNumberOfCellsRecursiveWithOverlap();
41 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithoutOverlap() const
43 return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
46 int MEDCouplingCartesianAMRPatchGen::getMaxNumberOfLevelsRelativeToThis() const
48 return _mesh->getMaxNumberOfLevelsRelativeToThis();
51 MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCartesianAMRMeshGen *mesh)
54 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen constructor : input mesh is NULL !");
55 _mesh=mesh; _mesh->incrRef();
58 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
60 const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
62 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe const : the mesh is NULL !");
66 MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
68 MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
70 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe : the mesh is NULL !");
74 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildren() const
76 std::vector<const BigMemoryObject *> ret;
77 if((const MEDCouplingCartesianAMRMeshGen *)_mesh)
78 ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
83 * \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.
84 * \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,
85 * a the end cell (\b excluded) of the range for the second element of the pair.
87 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight)
89 int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
91 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
94 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
96 return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
99 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
101 return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
105 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
106 * 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 !).
107 * Call isInMyNeighborhoodExt to deal with 2 patches not sharing directly the same father.
109 * \param [in] other - The other patch
110 * \param [in] ghostLev - The size of the neighborhood zone.
112 * \throw if \a this or \a other are invalid (end before start).
113 * \throw if \a ghostLev is \b not >= 0 .
114 * \throw if \a this and \a other have not the same space dimension.
116 * \sa isInMyNeighborhoodExt
118 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
121 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !");
123 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !");
124 const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
125 const std::vector< std::pair<int,int> >& otherp(other->getBLTRRange());
126 return IsInMyNeighborhood(ghostLev,thisp,otherp);
130 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
131 * 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
132 * ancestor must be the same. If they don't have the same ancestor an exception will be thrown.
134 * \param [in] other - The other patch
135 * \param [in] ghostLev - The size of the neighborhood zone.
137 * \throw if \a this or \a other are invalid (end before start).
138 * \throw if \a ghostLev is \b not >= 0 .
139 * \throw if \a this and \a other have not the same space dimension.
140 * \throw if there is not common ancestor of \a this and \a other.
142 * \sa isInMyNeighborhood, isInMyNeighborhoodDiffLev
144 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
147 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the size of the neighborhood must be >= 0 !");
149 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the input patch is NULL !");
151 const MEDCouplingCartesianAMRMeshGen *com(FindCommonAncestor(this,other,lev));//check that factors are OK
153 return isInMyNeighborhood(other,ghostLev);
154 std::vector<int> offset(ComputeOffsetFromTwoToOne(com,lev,this,other));
155 const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
156 std::vector< std::pair<int,int> > otherp(other->getBLTRRange());
157 otherp=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp,offset);
158 return IsInMyNeighborhood(ghostLev,thisp,otherp);
162 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
163 * the must be >= 0. This method works even if \a this and \a other does not share the same father.
164 * 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.
166 * \param [in] other - The other patch
167 * \param [in] ghostLev - The size of the neighborhood zone.
169 * \throw if \a this or \a other are invalid (end before start).
170 * \throw if \a ghostLev is \b not >= 0 .
171 * \throw if \a this and \a other have not the same space dimension.
172 * \throw if there is not common ancestor of \a this and \a other.
174 * \sa isInMyNeighborhoodExt
176 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
178 std::vector< std::pair<int,int> > thispp,otherpp;
179 std::vector<int> factors;
180 ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,this,other,thispp,otherpp,factors);
181 return IsInMyNeighborhood(ghostLev,thispp,otherpp);
184 std::vector<int> MEDCouplingCartesianAMRPatch::computeCellGridSt() const
186 const MEDCouplingCartesianAMRMeshGen *m(getMesh());
188 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no mesh held by this !");
189 const MEDCouplingCartesianAMRMeshGen *father(m->getFather());
191 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no father help by underlying mesh !");
192 const std::vector< std::pair<int,int> >& bltr(getBLTRRange());
193 const std::vector<int>& factors(father->getFactors());
194 std::vector<int> ret(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(bltr));
195 std::transform(ret.begin(),ret.end(),factors.begin(),ret.begin(),std::multiplies<int>());
199 bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::vector< std::pair<int,int> >& p1, const std::vector< std::pair<int,int> >& p2)
201 std::size_t thispsize(p1.size());
202 if(thispsize!=p2.size())
203 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !");
204 for(std::size_t i=0;i<thispsize;i++)
206 const std::pair<int,int>& thispp(p1[i]);
207 const std::pair<int,int>& otherpp(p2[i]);
208 if(thispp.second<thispp.first)
209 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
210 if(otherpp.second<otherpp.first)
211 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
212 if(otherpp.first==thispp.second+ghostLev-1)
214 if(otherpp.second+ghostLev-1==thispp.first)
216 int start(std::max(thispp.first,otherpp.first)),end(std::min(thispp.second,otherpp.second));
224 * \sa FindNeighborsOfSubPatchesOf
226 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
229 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev : the input pointers must be not NULL !");
230 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > ret;
231 std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()),p2Work(p2->getMesh()->getPatches());
232 while(!p1Work.empty())
234 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > retTmp;
235 std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2,p2Work2;
236 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it1=p1Work.begin();it1!=p1Work.end();it1++)
238 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
240 if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev))
241 retTmp.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it1,*it2));
243 std::vector<const MEDCouplingCartesianAMRPatch *> tmp1((*it1)->getMesh()->getPatches());
244 p1Work2.insert(p1Work2.end(),tmp1.begin(),tmp1.end());
246 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
248 std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it2)->getMesh()->getPatches());
249 p2Work2.insert(p2Work2.end(),tmp2.begin(),tmp2.end());
251 ret.push_back(retTmp);
259 * This method returns all pair of patches (pa,pb) so that pb is in the neighborhood of pa (size of neighborhood is \a ghostLev).
260 * 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
261 * FindNeighborsOfSubPatchesOfSameLev.
263 * \sa FindNeighborsOfSubPatchesOfSameLev
265 void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<const MEDCouplingCartesianAMRPatch *, const MEDCouplingCartesianAMRPatch *> >& ret)
268 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf : the input pointers must be not NULL !");
269 std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches());
270 while(!p1Work.empty())
272 std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2;
273 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it0=p1Work.begin();it0!=p1Work.end();it0++)
275 if((*it0)->isInMyNeighborhoodDiffLev(p2,ghostLev))
276 ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it0,p2));
277 std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it0)->getMesh()->getPatches());
278 p1Work2.insert(p1Work2.end(),tmp2.begin(),tmp2.end());
285 * \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.
287 * \saUpdateNeighborsOfOneWithTwoExt
289 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int ghostLev, const std::vector<int>& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
291 const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());
292 const std::vector< std::pair<int,int> >& p2BLTR(p2->getBLTRRange());
293 UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2);
297 * Idem than UpdateNeighborsOfOneWithTwo, except that here \a p1 and \a p2 are not sharing the same direct father.
299 * \sa UpdateNeighborsOfOneWithTwo
301 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
303 const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)]
304 std::vector< std::pair<int,int> > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)]
306 const MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev));
307 std::vector<int> offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4]
308 p2BLTR=MEDCouplingStructuredMesh::TranslateCompactFrmt(p2BLTR,offset);//p2BLTR=[(12,13),(4,9)]
309 UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1BLTR,p2BLTR,dataOnP1,dataOnP2);
313 * \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 !
315 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
317 std::vector< std::pair<int,int> > p1pp,p2pp;
318 std::vector<int> factors;
319 ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,p1,p2,p1pp,p2pp,factors);
321 std::vector<int> dimsP2NotRefined(p2->computeCellGridSt());
322 std::vector<int> dimsP2Refined(dimsP2NotRefined);
323 std::transform(dimsP2NotRefined.begin(),dimsP2NotRefined.end(),factors.begin(),dimsP2Refined.begin(),std::multiplies<int>());
324 std::vector< std::pair<int,int> > p2RefinedAbs(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsP2NotRefined));
325 std::vector<int> dimsP2RefinedGhost(dimsP2Refined.size());
326 std::transform(dimsP2Refined.begin(),dimsP2Refined.end(),dimsP2RefinedGhost.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));
327 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents());
328 MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev);
330 UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1pp,p2pp,dataOnP1,fineP2);
334 * \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 !
335 * 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
336 * on the same level as \a p1.
338 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)
340 std::vector<const MEDCouplingCartesianAMRMeshGen *> ancestorsOfThis;
341 const MEDCouplingCartesianAMRMeshGen *work(p1->getMesh()),*work2(0);
342 ancestorsOfThis.push_back(work);
345 work=work->getFather();
347 ancestorsOfThis.push_back(work);
352 std::size_t levThis(0),levOther(0);
353 while(work && !found)
356 work=work->getFather();
360 std::vector<const MEDCouplingCartesianAMRMeshGen *>::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work));
361 if(it!=ancestorsOfThis.end())
363 levThis=std::distance(ancestorsOfThis.begin(),it);
369 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : no common ancestor found !");
370 if(levThis<=levOther)
371 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : this method is not called correctly !");
373 const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]);
374 int idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2));
375 const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther));
376 std::vector<int> offset(ComputeOffsetFromTwoToOne(comAncestor,levOther,thisp,otherp));
377 p1Zone=thisp->getBLTRRange(); p2Zone=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset);
378 factToApplyOn2.resize(p1Zone.size()); std::fill(factToApplyOn2.begin(),factToApplyOn2.end(),1);
380 std::size_t nbOfTurn(levThis-levOther);
381 for(std::size_t i=0;i<nbOfTurn;i++)
383 std::vector< std::pair<int,int> > tmp0;
384 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1Zone,p2Zone,tmp0,false);
386 const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]);
387 ApplyFactorsOnCompactFrmt(p2Zone,curAncestor->getFactors());
388 curAncestor=ancestorsOfThis[levThis-1-i];
389 const std::vector<int>& factors(curAncestor->getFactors());
390 std::transform(factToApplyOn2.begin(),factToApplyOn2.end(),factors.begin(),factToApplyOn2.begin(),std::multiplies<int>());
391 int tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i]));
392 p1Zone=curAncestor->getPatch(tmpId)->getBLTRRange();
396 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
398 std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
399 ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
403 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, int& lev)
405 const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
407 while(f1!=f2 || f1==0 || f2==0)
409 f1=f1->getFather(); f2=f2->getFather();
410 if(f1->getFactors()!=f2->getFactors())
411 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : factors differ !");
415 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : no common ancestor between p1 and p2 !");
419 std::vector<int> MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, int lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
422 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : this method is useful only for lev > 0 !");
424 int dim(p1->getMesh()->getSpaceDimension());
425 if(p2->getMesh()->getSpaceDimension()!=dim)
426 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : dimension must be the same !");
427 std::vector< int > ret(dim,0);
428 for(int i=0;i<zeLev;i++)
430 const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
431 const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0);
432 for(int j=0;j<lev-i;j++)
434 const MEDCouplingCartesianAMRMeshGen *f1tmp(f1->getFather()),*f2tmp(f2->getFather());
435 int pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2));
436 p1h=f1tmp->getPatch(pid1); p2h=f2tmp->getPatch(pid2);
439 std::vector< std::pair<int,int> > p2c(p2h->getBLTRRange());
440 for(int k=0;k<dim;k++)
442 p2c[k].first+=ret[k];
443 p2c[k].second+=ret[k];
445 for(int k=0;k<dim;k++)
447 ret[k]=p2c[k].first-p1h->getBLTRRange()[k].first;
448 ret[k]*=f1->getFactors()[k];
454 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)
455 {//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)]
456 int dim((int)factors.size());
457 std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2]
458 std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
459 std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
460 std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
461 std::vector<int> fakeFactors(dim,1);
463 std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
464 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)]
465 ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)]
466 MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
467 std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
468 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)]
469 ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)]
470 MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
472 std::vector< std::pair<int,int> > dimsFine(p2);
473 ApplyFactorsOnCompactFrmt(dimsFine,factors);
474 ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
476 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
477 MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1);
481 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
482 * \param [in] factors - the factors per axis.
484 void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
486 std::size_t sz(factors.size());
487 if(sz!=partBeforeFact.size())
488 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
489 for(std::size_t i=0;i<sz;i++)
491 partBeforeFact[i].first*=factors[i];
492 partBeforeFact[i].second*=factors[i];
497 * This method is different than ApplyGhostOnCompactFrmt. The \a partBeforeFact parameter is enlarger contrary to ApplyGhostOnCompactFrmt.
499 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
500 * \param [in] ghostSize - the ghost size of zone for all axis.
502 void MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
505 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
506 std::size_t sz(partBeforeFact.size());
507 for(std::size_t i=0;i<sz;i++)
509 partBeforeFact[i].first-=ghostSize;
510 partBeforeFact[i].second+=ghostSize;
514 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
518 std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
520 return sizeof(MEDCouplingCartesianAMRPatchGF);
523 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMeshGen *gf):_gf(gf),_tlc(gf)
526 throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
530 void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
535 bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
537 bool ret(_tlc.keepTrackOfNewTL(gf));
549 int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const
551 return _mesh->getSpaceDimension();
554 void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFactors)
556 if(getSpaceDimension()!=(int)newFactors.size())
557 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : size of input factors is not equal to the space dimension !");
563 if(_factors==newFactors)
565 if(!_patches.empty())
566 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : modification of factors is not allowed when presence of patches !");
571 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
574 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
575 ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
580 * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this.
581 * The patches in \a this are ignored here.
582 * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap
584 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
586 return _mesh->getNumberOfCells();
590 * 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
591 * to take into account of the ghost cells for future computation.
592 * The patches in \a this are ignored here.
594 * \sa getNumberOfCellsAtCurrentLevel
596 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
598 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
599 return tmp->getNumberOfCells();
603 * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels
604 * starting from this. The set of cells which size is returned here are generally overlapping each other.
606 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
608 int ret(_mesh->getNumberOfCells());
609 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
611 ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
617 * This method returns the max number of cells covering all the space without overlapping.
618 * It returns the number of cells of the mesh with the highest resolution.
619 * The returned value is equal to the number of cells of mesh returned by buildUnstructured.
621 * \sa buildUnstructured
623 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
625 int ret(_mesh->getNumberOfCells());
626 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
628 ret-=(*it)->getNumberOfOverlapedCellsForFather();
629 ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
634 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getFather() const
639 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getGodFather() const
644 return _father->getGodFather();
648 * This method returns the level of \a this. 0 for god father. -1 for children of god father ...
650 int MEDCouplingCartesianAMRMeshGen::getAbsoluteLevel() const
655 return _father->getAbsoluteLevel()-1;
659 * This method returns grids relative to god father to specified level \a absoluteLev.
661 * \return std::vector<MEDCouplingCartesianAMRPatchGen *> - objects in vector are to be managed (decrRef) by the caller.
663 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(int absoluteLev) const
666 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !");
668 return getGodFather()->retrieveGridsAt(absoluteLev);
670 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > rets;
671 retrieveGridsAtInternal(absoluteLev,rets);
672 std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
673 for(std::size_t i=0;i<rets.size();i++)
675 ret[i]=rets[i].retn();
680 void MEDCouplingCartesianAMRMeshGen::detachFromFather()
687 * \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,
688 * a the end cell (\b excluded) of the range for the second element of the pair.
689 * \param [in] factors The factor of refinement per axis (different from 0).
691 void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
693 checkFactorsAndIfNotSetAssign(factors);
694 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
695 mesh->refineWithFactor(factors);
696 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
697 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
698 _patches.push_back(elt);
704 class InternalPatch : public RefCountObjectOnly
707 InternalPatch():_nb_of_true(0) { }
708 int getDimension() const { return (int)_part.size(); }
709 double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
710 int getNumberOfCells() const { return (int)_crit.size(); }
711 void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
712 std::vector<bool>& getCriterion() { return _crit; }
713 const std::vector<bool>& getConstCriterion() const { return _crit; }
714 void setPart(const std::vector< std::pair<int,int> >& part) { _part=part; }
715 std::vector< std::pair<int,int> >& getPart() { return _part; }
716 const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
717 bool presenceOfTrue() const { return _nb_of_true>0; }
718 std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
719 std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
720 double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
721 void zipToFitOnCriterion();
722 void updateNumberOfTrue() const;
723 MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
724 MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
728 mutable int _nb_of_true;
729 std::vector<bool> _crit;
731 std::vector< std::pair<int,int> > _part;
734 void InternalPatch::zipToFitOnCriterion()
736 std::vector<int> cgs(computeCGS());
737 std::vector<bool> newCrit;
738 std::vector< std::pair<int,int> > newPart,newPart2;
739 int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart));
740 MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
741 if(newNbOfTrue!=_nb_of_true)
742 throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
743 _crit=newCrit; _part=newPart2;
746 void InternalPatch::updateNumberOfTrue() const
748 _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
751 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
753 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
754 std::vector<int> cgs(computeCGS());
755 std::vector< std::pair<int,int> > newPart;
756 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
757 MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion());
758 ret->setPart(partInGlobal);
759 ret->updateNumberOfTrue();
763 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
765 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
770 void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
772 cutFound=false; cutPlace=-1;
773 std::vector<double> ratio(rangeOfAxisId-1);
774 for(int id=0;id<rangeOfAxisId-1;id++)
776 double efficiency[2];
779 std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
781 rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id;
783 rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id;
784 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
785 p->zipToFitOnCriterion();
787 efficiency[h]=p->getEfficiencyPerAxis(axisId);
789 ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]);
791 int minCellDirection(bso.getMinCellDirection()),indexMin(-1);
792 int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1));
793 std::vector<double> ratio_inner(dimRatioInner);
794 double minRatio(1.e10);
795 for(int i=0; i<dimRatioInner; i++)
797 if(ratio[minCellDirection-1+i]<minRatio)
799 minRatio=ratio[minCellDirection-1+i];
800 indexMin=i+minCellDirection;
803 cutFound=true; cutPlace=indexMin+patchToBeSplit->getConstPart()[axisId].first-1;
806 void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace)
808 cutPlace=-1; cutFound=false;
809 int minCellDirection(bso.getMinCellDirection());
810 const int dim(patchToBeSplit->getDimension());
811 std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
812 for(int id=0;id<dim;id++)
814 const std::vector<int>& signature(signatures[id]);
815 std::vector<int> hole;
816 std::vector<double> distance;
817 int len((int)signature.size());
818 for(int i=0;i<len;i++)
820 if(len>= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1)
824 double center(((double)len/2.));
825 for(std::size_t i=0;i<hole.size();i++)
826 distance.push_back(fabs(hole[i]+1.-center));
828 std::size_t posDistanceMin(std::distance(distance.begin(),std::min_element(distance.begin(),distance.end())));
831 cutPlace=hole[posDistanceMin]+patchToBeSplit->getConstPart()[axisId].first+1;
837 void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId)
839 cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
841 const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
842 int sign,minCellDirection(bso.getMinCellDirection());
843 const int dim(patchToBeSplit->getDimension());
845 std::vector<int> zeroCrossDims(dim,-1);
846 std::vector<int> zeroCrossVals(dim,-1);
847 std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
848 for (int id=0;id<dim;id++)
850 const std::vector<int>& signature(signatures[id]);
852 std::vector<int> derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ;
853 std::vector<double> distance ;
855 for (unsigned int i=1;i<signature.size()-1;i++)
856 derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
858 // Gradient absolute value
859 for ( unsigned int i=1;i<derivate_second_order.size();i++)
860 gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
861 if(derivate_second_order.empty())
863 for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
865 if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
867 if (derivate_second_order[i]*derivate_second_order[i+1] > 0 )
869 if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
871 if ( sign==0 || sign==-1 )
872 if ( i >= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 )
874 zero_cross.push_back(i) ;
875 edge.push_back(gradient_absolute[i]) ;
877 signe_change.push_back(sign) ;
879 if ( zero_cross.size() > 0 )
881 int max_cross=*max_element(edge.begin(),edge.end()) ;
882 for (unsigned int i=0;i<edge.size();i++)
883 if (edge[i]==max_cross)
884 max_cross_list.push_back(zero_cross[i]+1) ;
886 double center((signature.size()/2.0));
887 for (unsigned int i=0;i<max_cross_list.size();i++)
888 distance.push_back(fabs(max_cross_list[i]+1-center));
890 float distance_min=*min_element(distance.begin(),distance.end()) ;
891 int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
892 int best_place = max_cross_list[pos_distance_min] + part[id].first ;
895 zeroCrossDims[id] = best_place ;
896 zeroCrossVals[id] = max_cross ;
899 derivate_second_order.clear() ;
900 gradient_absolute.clear() ;
901 signe_change.clear() ;
904 max_cross_list.clear() ;
908 if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1 )
910 int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ;
912 if (zeroCrossVals[0]==max_cross_dims && zeroCrossVals[1]==max_cross_dims )
914 int nl_left(part[0].second-part[0].first);
915 int nc_left(part[1].second-part[1].first);
916 if ( nl_left >= nc_left )
922 max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin();
924 cutPlace=zeroCrossDims[max_cross_dims];
925 axisId=max_cross_dims ;
929 void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
932 if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd())
934 if(rangeOfAxisId>=2*bso.getMinCellDirection())
937 cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
942 if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells())
944 DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace);
949 MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
951 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
956 void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
958 MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
959 std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
960 std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
961 leftRect[axisId].second=cutPlace+1;
962 rightRect[axisId].first=cutPlace+1;
963 leftPart=patchToBeSplit->extractPart(leftRect);
964 rightPart=patchToBeSplit->extractPart(rightRect);
965 leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion();
966 listOfPatches.push_back(leftPart);
967 listOfPatches.push_back(rightPart);
973 * 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.
974 * This method only create patches at level 0 relative to \a this.
976 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
978 int nbCells(getNumberOfCellsAtCurrentLevel());
979 if(nbCells!=(int)criterion.size())
980 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
982 std::vector<int> cgs(_mesh->getCellGridStructure());
983 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
985 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
986 p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart()));
987 if(p->presenceOfTrue())
988 listOfPatches.push_back(p);
989 while(!listOfPatches.empty())
991 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
992 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
995 int axisId,rangeOfAxisId,cutPlace;
997 MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId);
998 if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()<bso.getMaxCells())
999 { listOfPatchesOK.push_back(DealWithNoCut(*it)); continue; }//action 1
1000 FindHole(bso,*it,axisId,cutFound,cutPlace);//axisId overwritten here if FindHole equal to true !
1002 { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
1003 FindInflection(bso,*it,cutFound,cutPlace,axisId);//axisId overwritten here if cutFound equal to true !
1005 { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
1006 TryAction4(bso,*it,axisId,rangeOfAxisId,cutFound,cutPlace);
1008 { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
1009 listOfPatchesOK.push_back(DealWithNoCut(*it));
1011 listOfPatches=listOfPatchesTmp;
1013 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
1014 addPatch((*it)->getConstPart(),factors);
1019 * 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.
1020 * This method only create patches at level 0 relative to \a this.
1022 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
1024 if(!criterion || !criterion->isAllocated())
1025 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
1026 std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
1027 createPatchesFromCriterion(bso,crit,factors);
1031 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayDouble *criterion, const std::vector<int>& factors, double eps)
1034 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : null criterion pointer !");
1035 std::vector<bool> inp(criterion->toVectorOfBool(eps));
1036 createPatchesFromCriterion(bso,inp,factors);
1040 * This method creates a multi level patches split at once.
1041 * This method calls as times as size of \a bso createPatchesFromCriterion. Size of \a bso and size of \a factors must be the same !
1044 * \param [in] criterion
1045 * \param [in] factors
1046 * \param [in] eps - See DataArrayDouble::toVectorOfBool for more information about the semantic of eps.
1048 * \sa createPatchesFromCriterion
1050 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterionML(const std::vector<const INTERP_KERNEL::BoxSplittingOptions *>& bso, const DataArrayDouble *criterion, const std::vector< std::vector<int> >& factors, double eps)
1052 std::size_t nbOfLevs(bso.size());
1053 if(nbOfLevs!=factors.size())
1054 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterionML : size of vectors must be the same !");
1058 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterionML : pointers in 1st arg must be not NULL !");
1059 createPatchesFromCriterion(*bso[0],criterion,factors[0],eps);
1060 for(std::size_t i=1;i<nbOfLevs;i++)
1063 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterionML : presence of a NULL BoxSplittingOptions in input vector !");
1065 std::vector<MEDCouplingCartesianAMRPatchGen *> elts(retrieveGridsAt((int)(i)));
1066 std::size_t sz(elts.size());
1067 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > elts2(sz);
1068 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > elts3(sz);
1069 for(std::size_t ii=0;ii<sz;ii++)
1072 static const char TMP_STR[]="TMP";
1073 std::vector< std::pair<std::string,int> > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1;
1074 MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> att(MEDCouplingAMRAttribute::New(this,fieldNames,0));
1076 DataArrayDouble *tmpDa(const_cast<DataArrayDouble *>(att->getFieldOn(this,TMP_STR)));
1077 tmpDa->cpyFrom(*criterion);
1078 att->synchronizeCoarseToFine();
1079 for(std::size_t ii=0;ii<sz;ii++)
1081 const DataArrayDouble *critOnLeaf(att->getFieldOn(const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh()),TMP_STR));
1082 elts3[ii]=const_cast<DataArrayDouble *>(critOnLeaf); elts3[ii]->incrRef();
1085 for(std::size_t ii=0;ii<sz;ii++)
1086 const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh())->createPatchesFromCriterion(*bso[i],elts3[ii],factors[i],eps);
1090 void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
1096 void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
1098 checkPatchId(patchId);
1099 int sz((int)_patches.size()),j(0);
1100 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
1101 for(int i=0;i<sz;i++)
1103 patches[j++]=_patches[i];
1104 (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
1109 int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
1111 return (int)_patches.size();
1114 int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
1117 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
1119 if((*it)->getMesh()==mesh)
1122 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
1125 std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
1127 std::size_t sz(_patches.size());
1128 std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
1129 for(std::size_t i=0;i<sz;i++)
1134 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const
1136 checkPatchId(patchId);
1137 return _patches[patchId];
1141 * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1).
1142 * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !).
1144 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
1146 const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
1147 return p1->isInMyNeighborhood(p2,GetGhostLevelInFineRef(ghostLev,_factors));
1151 * 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.
1152 * 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
1153 * defined by the patch with id \a patchId.
1155 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1156 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1157 * \return DataArrayDouble * - The array of the cell field on the requested patch
1159 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1160 * \throw if \a cellFieldOnThis is NULL or not allocated
1161 * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine
1163 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const
1165 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1166 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1167 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1168 const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
1169 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
1170 ret->copyStringInfoFrom(*cellFieldOnThis);
1171 MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
1176 * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of creating a new instance
1177 * it fills the value into the \a cellFieldOnPatch data.
1179 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1180 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1181 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1183 * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
1185 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, bool isConservative) const
1187 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1188 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1189 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1190 MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
1193 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1194 std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
1199 * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the
1200 * potential neighbor patches covered by the ghost cells of patch with id \a patchId.
1202 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1203 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1204 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1205 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1207 * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
1209 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev, bool isConservative) const
1211 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1212 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
1213 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1214 MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1217 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1218 std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
1223 * This method is equivalent to fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
1224 * in \a cellFieldOnPatch.
1226 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1227 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1228 * \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.
1229 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1231 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
1233 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1234 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
1235 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1236 MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1240 * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
1241 * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
1243 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1244 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1245 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1246 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1247 * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
1249 * \sa fillCellFieldOnPatchOnlyGhostAdv
1251 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches, bool isConservative) const
1253 int nbp(getNumberOfPatches());
1254 if(nbp!=(int)arrsOnPatches.size())
1256 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1257 throw INTERP_KERNEL::Exception(oss.str().c_str());
1259 DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1260 // first, do as usual
1261 fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev,isConservative);
1262 fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
1266 * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
1267 * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
1269 * \sa getPatchIdsInTheNeighborhoodOf
1271 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
1273 int nbp(getNumberOfPatches());
1274 if(nbp!=(int)arrsOnPatches.size())
1276 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1277 throw INTERP_KERNEL::Exception(oss.str().c_str());
1279 const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
1280 DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1281 std::vector<int> ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
1282 for(std::vector<int>::const_iterator it=ids.begin();it!=ids.end();it++)
1284 const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it));
1285 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]);
1289 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const
1291 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor);
1295 * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
1297 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1298 * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1299 * \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.
1300 * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
1302 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1303 * \throw if \a cellFieldOnPatch is NULL or not allocated
1304 * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
1306 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, bool isConservative) const
1308 if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1309 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
1310 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1311 MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
1314 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1315 MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis);
1320 * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this
1321 * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch.
1323 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1324 * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1325 * \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.
1326 * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
1327 * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
1329 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1330 * \throw if \a cellFieldOnPatch is NULL or not allocated
1331 * \sa fillCellFieldComingFromPatch
1333 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev, bool isConservative) const
1335 if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1336 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
1337 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1338 MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
1341 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1342 MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis);
1347 * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is
1348 * defined by ghostLev.
1350 * \param [in] patchId - the id of the considered patch.
1351 * \param [in] ghostLev - the size of the neighborhood.
1352 * \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.
1354 DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const
1356 int nbp(getNumberOfPatches());
1357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1358 for(int i=0;i<nbp;i++)
1361 if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1362 ret->pushBackSilent(i);
1367 MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
1369 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1370 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1371 std::vector<int> cgs(_mesh->getCellGridStructure());
1372 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
1374 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1376 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1377 msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
1379 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1380 msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1381 std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
1382 for(std::size_t i=0;i<msSafe.size();i++)
1384 return MEDCouplingUMesh::MergeUMeshes(ms);
1388 * This method returns a mesh containing as cells that there is patches at the current level.
1389 * The patches are seen like 'boxes' that is too say the refinement will not appear here.
1391 * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
1393 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
1395 std::vector<const MEDCoupling1SGTUMesh *> cells;
1396 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
1397 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1399 const MEDCouplingCartesianAMRPatch *patch(*it);
1402 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
1403 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
1404 cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
1407 return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
1410 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
1412 std::vector<const MEDCoupling1SGTUMesh *> patches;
1413 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > patchesSafe;
1414 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1416 const MEDCouplingCartesianAMRPatch *patch(*it);
1419 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
1420 patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
1423 return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
1427 * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
1428 * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
1429 * \sa buildUnstructured
1431 MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
1433 if(recurseArrs.empty())
1434 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
1436 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1437 std::vector<int> cgs(_mesh->getCellGridStructure());
1438 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
1440 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1442 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1443 std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
1444 msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
1446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1448 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
1449 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
1450 arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
1451 ret->setArray(arr2);
1452 ret->setName(arr2->getName());
1453 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1454 MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1458 std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
1459 for(std::size_t i=0;i<msSafe.size();i++)
1462 return MEDCouplingFieldDouble::MergeFields(ms);
1466 * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
1467 * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
1469 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const
1471 std::vector<int> st(_mesh->getCellGridStructure());
1472 std::vector< std::pair<int,int> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
1473 std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus<int>(),2*ghostSz));
1474 MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz);
1475 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
1480 * This method returns all the patches in \a this not equal to \a patchId that are in neighborhood of patch with id \a patchId.
1482 * \sa fillCellFieldOnPatchOnlyGhostAdv
1484 std::vector<int> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(int patchId, int ghostLev) const
1486 std::vector<int> ret;
1487 int nbp(getNumberOfPatches());
1489 for(int i=0;i<nbp;i++)
1492 if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1498 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1499 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
1501 _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1504 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):_father(father)
1507 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : empty father !");
1509 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
1510 mesh->checkCoherency();
1511 _mesh=mesh; _mesh->incrRef();
1514 void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const
1516 int sz(getNumberOfPatches());
1517 if(patchId<0 || patchId>=sz)
1519 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
1520 throw INTERP_KERNEL::Exception(oss.str().c_str());
1524 void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector<int>& factors)
1526 if(getSpaceDimension()!=(int)factors.size())
1527 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !");
1528 if(_factors.empty())
1534 if(_factors!=factors)
1535 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : the factors ");
1539 void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> >& grids) const
1543 const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
1544 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
1545 grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
1549 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1551 const MEDCouplingCartesianAMRPatch *pt(*it);
1554 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> tmp1(*it);
1555 grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
1561 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1563 const MEDCouplingCartesianAMRPatch *pt(*it);
1565 pt->getMesh()->retrieveGridsAtInternal(lev-1,grids);
1570 int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const std::vector<int>& factors)
1573 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !");
1575 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !");
1576 int ghostLevInPatchRef;
1578 ghostLevInPatchRef=0;
1581 ghostLevInPatchRef=(ghostLev-1)/factors[0]+1;
1582 for(std::size_t i=0;i<factors.size();i++)
1583 ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/factors[i]+1);
1585 return ghostLevInPatchRef;
1589 * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
1590 * Elements in \a all are expected to be sorted from god father to most refined structure.
1592 std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
1594 int maxLev(getMaxNumberOfLevelsRelativeToThis());
1595 std::vector<const DataArrayDouble *> ret;
1596 std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
1598 for(int i=0;i<maxLev;i++)
1600 std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
1601 for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
1603 if((*it)==head || head->isObjectInTheProgeny(*it))
1604 ret.push_back(all[kk]);
1606 std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
1607 for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
1609 const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
1610 meshesTmp.push_back(mesh);
1616 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
1620 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
1622 return sizeof(MEDCouplingCartesianAMRMeshGen);
1625 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildren() const
1627 std::vector<const BigMemoryObject *> ret;
1628 if((const MEDCouplingIMesh *)_mesh)
1629 ret.push_back((const MEDCouplingIMesh *)_mesh);
1630 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1632 if((const MEDCouplingCartesianAMRPatch*)*it)
1633 ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
1638 void MEDCouplingCartesianAMRMeshGen::updateTime() const
1640 if((const MEDCouplingIMesh *)_mesh)
1641 updateTimeWith(*_mesh);
1642 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1644 const MEDCouplingCartesianAMRPatch *elt(*it);
1647 const MEDCouplingCartesianAMRMeshGen *mesh(elt->getMesh());
1649 updateTimeWith(*mesh);
1653 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(father,mesh)
1657 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1658 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1660 return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1663 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1664 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
1668 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
1670 std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren());
1674 MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()