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 "MEDCouplingFieldDouble.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingIMesh.hxx"
25 #include "MEDCouplingUMesh.hxx"
31 using namespace ParaMEDMEM;
35 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithOverlap() const
37 return _mesh->getNumberOfCellsRecursiveWithOverlap();
40 int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithoutOverlap() const
42 return _mesh->getNumberOfCellsRecursiveWithoutOverlap();
45 int MEDCouplingCartesianAMRPatchGen::getMaxNumberOfLevelsRelativeToThis() const
47 return _mesh->getMaxNumberOfLevelsRelativeToThis();
50 MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCartesianAMRMeshGen *mesh)
53 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen constructor : input mesh is NULL !");
54 _mesh=mesh; _mesh->incrRef();
57 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
59 const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
61 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe const : the mesh is NULL !");
65 MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
67 MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
69 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe : the mesh is NULL !");
73 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildren() const
75 std::vector<const BigMemoryObject *> ret;
76 if((const MEDCouplingCartesianAMRMeshGen *)_mesh)
77 ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
82 * \param [in] mesh not null pointer of refined mesh replacing the cell range of \a father defined by the bottom left and top right just after.
83 * \param [in] bottomLeftTopRight a vector equal to the space dimension of \a mesh that specifies for each dimension, the included cell start of the range for the first element of the pair,
84 * a the end cell (\b excluded) of the range for the second element of the pair.
86 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight)
88 int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
90 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
93 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
95 return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
98 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
100 return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
104 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
105 * the must be >= 0. \b WARNING this method only works if \a this and \a other share the same father (no check of this will be done !).
106 * Call isInMyNeighborhoodExt to deal with 2 patches not sharing directly the same father.
108 * \param [in] other - The other patch
109 * \param [in] ghostLev - The size of the neighborhood zone.
111 * \throw if \a this or \a other are invalid (end before start).
112 * \throw if \a ghostLev is \b not >= 0 .
113 * \throw if \a this and \a other have not the same space dimension.
115 * \sa isInMyNeighborhoodExt
117 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
120 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !");
122 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !");
123 const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
124 const std::vector< std::pair<int,int> >& otherp(other->getBLTRRange());
125 return IsInMyNeighborhood(ghostLev,thisp,otherp);
129 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
130 * 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
131 * ancestor must be the same. If they don't have the same ancestor an exception will be thrown.
133 * \param [in] other - The other patch
134 * \param [in] ghostLev - The size of the neighborhood zone.
136 * \throw if \a this or \a other are invalid (end before start).
137 * \throw if \a ghostLev is \b not >= 0 .
138 * \throw if \a this and \a other have not the same space dimension.
139 * \throw if there is not common ancestor of \a this and \a other.
141 * \sa isInMyNeighborhood, isInMyNeighborhoodDiffLev
143 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
146 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the size of the neighborhood must be >= 0 !");
148 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the input patch is NULL !");
150 const MEDCouplingCartesianAMRMeshGen *com(FindCommonAncestor(this,other,lev));//check that factors are OK
152 return isInMyNeighborhood(other,ghostLev);
153 std::vector<int> offset(ComputeOffsetFromTwoToOne(com,lev,this,other));
154 const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
155 std::vector< std::pair<int,int> > otherp(other->getBLTRRange());
156 otherp=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp,offset);
157 return IsInMyNeighborhood(ghostLev,thisp,otherp);
161 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
162 * the must be >= 0. This method works even if \a this and \a other does not share the same father.
163 * 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.
165 * \param [in] other - The other patch
166 * \param [in] ghostLev - The size of the neighborhood zone.
168 * \throw if \a this or \a other are invalid (end before start).
169 * \throw if \a ghostLev is \b not >= 0 .
170 * \throw if \a this and \a other have not the same space dimension.
171 * \throw if there is not common ancestor of \a this and \a other.
173 * \sa isInMyNeighborhoodExt
175 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
177 std::vector<const MEDCouplingCartesianAMRMeshGen *> ancestorsOfThis;
178 const MEDCouplingCartesianAMRMeshGen *work(getMesh()),*work2(0);
179 ancestorsOfThis.push_back(work);
182 work=work->getFather();
184 ancestorsOfThis.push_back(work);
187 work=other->getMesh();
189 std::size_t levThis(0),levOther(0);
190 while(work && !found)
193 work=work->getFather();
197 std::vector<const MEDCouplingCartesianAMRMeshGen *>::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work));
198 if(it!=ancestorsOfThis.end())
200 levThis=std::distance(ancestorsOfThis.begin(),it);
206 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev : no common ancestor found !");
207 if(levThis<=levOther)
208 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev : this method is not called correctly !");
210 const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]);
211 int idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2));
212 const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther));
213 std::vector<int> offset(ComputeOffsetFromTwoToOne(comAncestor,levOther,thisp,otherp));
214 std::vector< std::pair<int,int> > thispp(thisp->getBLTRRange()),otherpp(MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset));
216 std::size_t nbOfTurn(levThis-levOther);
217 for(std::size_t i=0;i<nbOfTurn;i++)
219 std::vector< std::pair<int,int> > tmp0;
220 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(thispp,otherpp,tmp0,false);
222 const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]);
223 ApplyFactorsOnCompactFrmt(otherpp,curAncestor->getFactors());
224 curAncestor=ancestorsOfThis[levThis-1-i];
225 int tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i]));
226 thispp=curAncestor->getPatch(tmpId)->getBLTRRange();
228 return IsInMyNeighborhood(ghostLev,thispp,otherpp);
231 bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::vector< std::pair<int,int> >& p1, const std::vector< std::pair<int,int> >& p2)
233 std::size_t thispsize(p1.size());
234 if(thispsize!=p2.size())
235 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !");
236 for(std::size_t i=0;i<thispsize;i++)
238 const std::pair<int,int>& thispp(p1[i]);
239 const std::pair<int,int>& otherpp(p2[i]);
240 if(thispp.second<thispp.first)
241 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
242 if(otherpp.second<otherpp.first)
243 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
244 if(otherpp.first==thispp.second+ghostLev-1)
246 if(otherpp.second+ghostLev-1==thispp.first)
248 int start(std::max(thispp.first,otherpp.first)),end(std::min(thispp.second,otherpp.second));
256 * \sa FindNeighborsOfSubPatchesOf
258 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
261 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev : the input pointers must be not NULL !");
262 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > ret;
263 std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()),p2Work(p2->getMesh()->getPatches());
264 while(!p1Work.empty())
266 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > retTmp;
267 std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2,p2Work2;
268 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it1=p1Work.begin();it1!=p1Work.end();it1++)
270 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
272 if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev))
273 retTmp.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it1,*it2));
275 std::vector<const MEDCouplingCartesianAMRPatch *> tmp1((*it1)->getMesh()->getPatches());
276 p1Work2.insert(p1Work2.end(),tmp1.begin(),tmp1.end());
278 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
280 std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it2)->getMesh()->getPatches());
281 p2Work2.insert(p2Work2.end(),tmp2.begin(),tmp2.end());
283 ret.push_back(retTmp);
291 * This method returns all pair of patches (pa,pb) so that pb is in the neighborhood of pa (size of neighborhood is \a ghostLev).
292 * 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
293 * FindNeighborsOfSubPatchesOfSameLev.
295 * \sa FindNeighborsOfSubPatchesOfSameLev
297 void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<const MEDCouplingCartesianAMRPatch *, const MEDCouplingCartesianAMRPatch *> >& ret)
300 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf : the input pointers must be not NULL !");
301 std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches());
302 while(!p1Work.empty())
304 std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2;
305 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it0=p1Work.begin();it0!=p1Work.end();it0++)
307 if((*it0)->isInMyNeighborhoodDiffLev(p2,ghostLev))
308 ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it0,p2));
309 std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it0)->getMesh()->getPatches());
310 p1Work2.insert(p1Work2.end(),tmp2.begin(),tmp2.end());
317 * \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.
319 * \saUpdateNeighborsOfOneWithTwoExt
321 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int ghostLev, const std::vector<int>& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
323 const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());
324 const std::vector< std::pair<int,int> >& p2BLTR(p2->getBLTRRange());
325 UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2);
328 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)
329 {//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)]
330 int dim((int)factors.size());
331 std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2]
332 std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
333 std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
334 std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
335 std::vector<int> fakeFactors(dim,1);
337 std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
338 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)]
339 ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)]
340 ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
341 std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
342 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)]
343 ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)]
344 MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
346 std::vector< std::pair<int,int> > dimsFine(p2);
347 ApplyFactorsOnCompactFrmt(dimsFine,factors);
348 ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
350 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
351 MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1);
355 * Idem than UpdateNeighborsOfOneWithTwo, except that here \a p1 and \a p2 are not sharing the same direct father.
357 * \sa UpdateNeighborsOfOneWithTwo
359 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
361 const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)]
362 std::vector< std::pair<int,int> > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)]
364 const MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev));
365 std::vector<int> offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4]
366 p2BLTR=MEDCouplingStructuredMesh::TranslateCompactFrmt(p2BLTR,offset);//p2BLTR=[(12,13),(4,9)]
367 UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1BLTR,p2BLTR,dataOnP1,dataOnP2);
370 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
374 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
376 std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
377 ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
381 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, int& lev)
383 const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
385 while(f1!=f2 || f1==0 || f2==0)
387 f1=f1->getFather(); f2=f2->getFather();
388 if(f1->getFactors()!=f2->getFactors())
389 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : factors differ !");
393 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : no common ancestor between p1 and p2 !");
397 std::vector<int> MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, int lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
400 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : this method is useful only for lev > 0 !");
402 int dim(p1->getMesh()->getSpaceDimension());
403 if(p2->getMesh()->getSpaceDimension()!=dim)
404 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : dimension must be the same !");
405 std::vector< int > ret(dim,0);
406 for(int i=0;i<zeLev;i++)
408 const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
409 const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0);
410 for(int j=0;j<lev-i;j++)
412 const MEDCouplingCartesianAMRMeshGen *f1tmp(f1->getFather()),*f2tmp(f2->getFather());
413 int pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2));
414 p1h=f1tmp->getPatch(pid1); p2h=f2tmp->getPatch(pid2);
417 std::vector< std::pair<int,int> > p2c(p2h->getBLTRRange());
418 for(int k=0;k<dim;k++)
420 p2c[k].first+=ret[k];
421 p2c[k].second+=ret[k];
423 for(int k=0;k<dim;k++)
425 ret[k]=p2c[k].first-p1h->getBLTRRange()[k].first;
426 ret[k]*=f1->getFactors()[k];
433 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
434 * \param [in] factors - the factors per axis.
436 void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
438 std::size_t sz(factors.size());
439 if(sz!=partBeforeFact.size())
440 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
441 for(std::size_t i=0;i<sz;i++)
443 partBeforeFact[i].first*=factors[i];
444 partBeforeFact[i].second*=factors[i];
449 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
450 * \param [in] ghostSize - the ghost size of zone for all axis.
452 void MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
455 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !");
456 std::size_t sz(partBeforeFact.size());
457 for(std::size_t i=0;i<sz;i++)
459 partBeforeFact[i].first+=ghostSize;
460 partBeforeFact[i].second+=ghostSize;
465 * This method is different than ApplyGhostOnCompactFrmt. The \a partBeforeFact parameter is enlarger contrary to ApplyGhostOnCompactFrmt.
467 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
468 * \param [in] ghostSize - the ghost size of zone for all axis.
470 void MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
473 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
474 std::size_t sz(partBeforeFact.size());
475 for(std::size_t i=0;i<sz;i++)
477 partBeforeFact[i].first-=ghostSize;
478 partBeforeFact[i].second+=ghostSize;
482 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
486 std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
488 return sizeof(MEDCouplingCartesianAMRPatchGF);
491 MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf)
494 throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
498 void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
503 bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
505 bool ret(_tlc.keepTrackOfNewTL(gf));
515 int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const
517 return _mesh->getSpaceDimension();
520 void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFactors)
522 if(getSpaceDimension()!=(int)newFactors.size())
523 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : size of input factors is not equal to the space dimension !");
529 if(_factors==newFactors)
531 if(!_patches.empty())
532 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : modification of factors is not allowed when presence of patches !");
537 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
540 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
541 ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
546 * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this.
547 * The patches in \a this are ignored here.
548 * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap
550 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
552 return _mesh->getNumberOfCells();
556 * 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
557 * to take into account of the ghost cells for future computation.
558 * The patches in \a this are ignored here.
560 * \sa getNumberOfCellsAtCurrentLevel
562 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
564 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
565 return tmp->getNumberOfCells();
569 * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels
570 * starting from this. The set of cells which size is returned here are generally overlapping each other.
572 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
574 int ret(_mesh->getNumberOfCells());
575 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
577 ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
583 * This method returns the max number of cells covering all the space without overlapping.
584 * It returns the number of cells of the mesh with the highest resolution.
585 * The returned value is equal to the number of cells of mesh returned by buildUnstructured.
587 * \sa buildUnstructured
589 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
591 int ret(_mesh->getNumberOfCells());
592 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
594 ret-=(*it)->getNumberOfOverlapedCellsForFather();
595 ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
600 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getFather() const
605 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getGodFather() const
610 return _father->getGodFather();
614 * This method returns the level of \a this. 0 for god father. -1 for children of god father ...
616 int MEDCouplingCartesianAMRMeshGen::getAbsoluteLevel() const
621 return _father->getAbsoluteLevel()-1;
625 * This method returns grids relative to god father to specified level \a absoluteLev.
627 * \return std::vector<MEDCouplingCartesianAMRPatchGen *> - objects in vector are to be managed (decrRef) by the caller.
629 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(int absoluteLev) const
632 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !");
634 return getGodFather()->retrieveGridsAt(absoluteLev);
636 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > rets;
637 retrieveGridsAtInternal(absoluteLev,rets);
638 std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
639 for(std::size_t i=0;i<rets.size();i++)
641 ret[i]=rets[i].retn();
646 void MEDCouplingCartesianAMRMeshGen::detachFromFather()
653 * \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,
654 * a the end cell (\b excluded) of the range for the second element of the pair.
655 * \param [in] factors The factor of refinement per axis (different from 0).
657 void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
659 checkFactorsAndIfNotSetAssign(factors);
660 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
661 mesh->refineWithFactor(factors);
662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
663 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
664 _patches.push_back(elt);
670 class InternalPatch : public RefCountObjectOnly
673 InternalPatch():_nb_of_true(0) { }
674 int getDimension() const { return (int)_part.size(); }
675 double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
676 int getNumberOfCells() const { return (int)_crit.size(); }
677 void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
678 std::vector<bool>& getCriterion() { return _crit; }
679 const std::vector<bool>& getConstCriterion() const { return _crit; }
680 void setPart(const std::vector< std::pair<int,int> >& part) { _part=part; }
681 std::vector< std::pair<int,int> >& getPart() { return _part; }
682 const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
683 bool presenceOfTrue() const { return _nb_of_true>0; }
684 std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
685 std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
686 double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
687 void zipToFitOnCriterion();
688 void updateNumberOfTrue() const;
689 MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
690 MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
694 mutable int _nb_of_true;
695 std::vector<bool> _crit;
697 std::vector< std::pair<int,int> > _part;
700 void InternalPatch::zipToFitOnCriterion()
702 std::vector<int> cgs(computeCGS());
703 std::vector<bool> newCrit;
704 std::vector< std::pair<int,int> > newPart,newPart2;
705 int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart));
706 MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
707 if(newNbOfTrue!=_nb_of_true)
708 throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
709 _crit=newCrit; _part=newPart2;
712 void InternalPatch::updateNumberOfTrue() const
714 _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
717 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
719 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
720 std::vector<int> cgs(computeCGS());
721 std::vector< std::pair<int,int> > newPart;
722 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
723 MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion());
724 ret->setPart(partInGlobal);
725 ret->updateNumberOfTrue();
729 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
731 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
736 void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
738 cutFound=false; cutPlace=-1;
739 std::vector<double> ratio(rangeOfAxisId-1);
740 for(int id=0;id<rangeOfAxisId-1;id++)
742 double efficiency[2];
745 std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
747 rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id;
749 rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id;
750 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
751 p->zipToFitOnCriterion();
753 efficiency[h]=p->getEfficiencyPerAxis(axisId);
755 ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]);
757 int minCellDirection(bso.getMinCellDirection()),indexMin(-1);
758 int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1));
759 std::vector<double> ratio_inner(dimRatioInner);
760 double minRatio(1.e10);
761 for(int i=0; i<dimRatioInner; i++)
763 if(ratio[minCellDirection-1+i]<minRatio)
765 minRatio=ratio[minCellDirection-1+i];
766 indexMin=i+minCellDirection;
769 cutFound=true; cutPlace=indexMin+patchToBeSplit->getConstPart()[axisId].first-1;
772 void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace)
774 cutPlace=-1; cutFound=false;
775 int minCellDirection(bso.getMinCellDirection());
776 const int dim(patchToBeSplit->getDimension());
777 std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
778 for(int id=0;id<dim;id++)
780 const std::vector<int>& signature(signatures[id]);
781 std::vector<int> hole;
782 std::vector<double> distance;
783 int len((int)signature.size());
784 for(int i=0;i<len;i++)
786 if(len>= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1)
790 double center(((double)len/2.));
791 for(std::size_t i=0;i<hole.size();i++)
792 distance.push_back(fabs(hole[i]+1.-center));
794 std::size_t posDistanceMin(std::distance(distance.begin(),std::min_element(distance.begin(),distance.end())));
797 cutPlace=hole[posDistanceMin]+patchToBeSplit->getConstPart()[axisId].first+1;
803 void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId)
805 cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
807 const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
808 int sign,minCellDirection(bso.getMinCellDirection());
809 const int dim(patchToBeSplit->getDimension());
811 std::vector<int> zeroCrossDims(dim,-1);
812 std::vector<int> zeroCrossVals(dim,-1);
813 std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
814 for (int id=0;id<dim;id++)
816 const std::vector<int>& signature(signatures[id]);
818 std::vector<int> derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ;
819 std::vector<double> distance ;
821 for (unsigned int i=1;i<signature.size()-1;i++)
822 derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
824 // Gradient absolute value
825 for ( unsigned int i=1;i<derivate_second_order.size();i++)
826 gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
827 if(derivate_second_order.empty())
829 for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
831 if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
833 if (derivate_second_order[i]*derivate_second_order[i+1] > 0 )
835 if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
837 if ( sign==0 || sign==-1 )
838 if ( i >= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 )
840 zero_cross.push_back(i) ;
841 edge.push_back(gradient_absolute[i]) ;
843 signe_change.push_back(sign) ;
845 if ( zero_cross.size() > 0 )
847 int max_cross=*max_element(edge.begin(),edge.end()) ;
848 for (unsigned int i=0;i<edge.size();i++)
849 if (edge[i]==max_cross)
850 max_cross_list.push_back(zero_cross[i]+1) ;
852 double center((signature.size()/2.0));
853 for (unsigned int i=0;i<max_cross_list.size();i++)
854 distance.push_back(fabs(max_cross_list[i]+1-center));
856 float distance_min=*min_element(distance.begin(),distance.end()) ;
857 int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
858 int best_place = max_cross_list[pos_distance_min] + part[id].first ;
861 zeroCrossDims[id] = best_place ;
862 zeroCrossVals[id] = max_cross ;
865 derivate_second_order.clear() ;
866 gradient_absolute.clear() ;
867 signe_change.clear() ;
870 max_cross_list.clear() ;
874 if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1 )
876 int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ;
878 if (zeroCrossVals[0]==max_cross_dims && zeroCrossVals[1]==max_cross_dims )
880 int nl_left(part[0].second-part[0].first);
881 int nc_left(part[1].second-part[1].first);
882 if ( nl_left >= nc_left )
888 max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin();
890 cutPlace=zeroCrossDims[max_cross_dims];
891 axisId=max_cross_dims ;
895 void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
898 if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd())
900 if(rangeOfAxisId>=2*bso.getMinCellDirection())
903 cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
908 if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells())
910 DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace);
915 MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
917 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
922 void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
924 MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
925 std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
926 std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
927 leftRect[axisId].second=cutPlace+1;
928 rightRect[axisId].first=cutPlace+1;
929 leftPart=patchToBeSplit->extractPart(leftRect);
930 rightPart=patchToBeSplit->extractPart(rightRect);
931 leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion();
932 listOfPatches.push_back(leftPart);
933 listOfPatches.push_back(rightPart);
939 * 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.
941 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
943 int nbCells(getNumberOfCellsAtCurrentLevel());
944 if(nbCells!=(int)criterion.size())
945 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 !");
947 std::vector<int> cgs(_mesh->getCellGridStructure());
948 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
950 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
951 p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart()));
952 if(p->presenceOfTrue())
953 listOfPatches.push_back(p);
954 while(!listOfPatches.empty())
956 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
957 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
960 int axisId,rangeOfAxisId,cutPlace;
962 MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId);
963 if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()<bso.getMaxCells())
964 { listOfPatchesOK.push_back(DealWithNoCut(*it)); continue; }//action 1
965 FindHole(bso,*it,axisId,cutFound,cutPlace);//axisId overwritten here if FindHole equal to true !
967 { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
968 FindInflection(bso,*it,cutFound,cutPlace,axisId);//axisId overwritten here if cutFound equal to true !
970 { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
971 TryAction4(bso,*it,axisId,rangeOfAxisId,cutFound,cutPlace);
973 { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
974 listOfPatchesOK.push_back(DealWithNoCut(*it));
976 listOfPatches=listOfPatchesTmp;
978 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
979 addPatch((*it)->getConstPart(),factors);
984 * 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.
986 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
988 if(!criterion || !criterion->isAllocated())
989 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
990 std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
991 createPatchesFromCriterion(bso,crit,factors);
995 void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
1001 void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
1003 checkPatchId(patchId);
1004 int sz((int)_patches.size()),j(0);
1005 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
1006 for(int i=0;i<sz;i++)
1008 patches[j++]=_patches[i];
1009 (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
1014 int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
1016 return (int)_patches.size();
1019 int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
1022 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
1024 if((*it)->getMesh()==mesh)
1027 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
1030 std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
1032 std::size_t sz(_patches.size());
1033 std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
1034 for(std::size_t i=0;i<sz;i++)
1039 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const
1041 checkPatchId(patchId);
1042 return _patches[patchId];
1046 * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1).
1047 * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !).
1049 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
1051 const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
1052 return p1->isInMyNeighborhood(p2,GetGhostLevelInFineRef(ghostLev,_factors));
1056 * 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.
1057 * 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
1058 * defined by the patch with id \a patchId.
1060 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1061 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1062 * \return DataArrayDouble * - The array of the cell field on the requested patch
1064 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1065 * \throw if \a cellFieldOnThis is NULL or not allocated
1066 * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine
1068 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const
1070 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1071 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1072 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1073 const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
1074 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
1075 ret->copyStringInfoFrom(*cellFieldOnThis);
1076 MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
1081 * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of creating a new instance
1082 * it fills the value into the \a cellFieldOnPatch data.
1084 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1085 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1086 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1088 * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
1090 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const
1092 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1093 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1094 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1095 MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
1099 * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the
1100 * potential neighbor patches covered by the ghost cells of patch with id \a patchId.
1102 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1103 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1104 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1105 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1107 * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
1109 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
1111 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1112 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
1113 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1114 MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1118 * This method is equivalent to fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
1119 * in \a cellFieldOnPatch.
1121 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1122 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1123 * \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.
1124 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1126 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
1128 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1129 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
1130 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1131 MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1135 * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
1136 * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
1138 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1139 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1140 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1141 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1142 * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
1144 * \sa fillCellFieldOnPatchOnlyGhostAdv
1146 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
1148 int nbp(getNumberOfPatches());
1149 if(nbp!=(int)arrsOnPatches.size())
1151 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1152 throw INTERP_KERNEL::Exception(oss.str().c_str());
1154 DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1155 // first, do as usual
1156 fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev);
1157 fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
1161 * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
1162 * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
1164 * \sa getPatchIdsInTheNeighborhoodOf
1166 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
1168 int nbp(getNumberOfPatches());
1169 if(nbp!=(int)arrsOnPatches.size())
1171 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1172 throw INTERP_KERNEL::Exception(oss.str().c_str());
1174 const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
1175 DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1176 std::vector<int> ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
1177 for(std::vector<int>::const_iterator it=ids.begin();it!=ids.end();it++)
1179 const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it));
1180 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]);
1184 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const
1186 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor);
1190 * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
1192 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1193 * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1194 * \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.
1196 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1197 * \throw if \a cellFieldOnPatch is NULL or not allocated
1198 * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
1200 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const
1202 if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1203 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
1204 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1205 MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
1209 * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this
1210 * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch.
1212 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1213 * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1214 * \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.
1215 * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
1217 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1218 * \throw if \a cellFieldOnPatch is NULL or not allocated
1219 * \sa fillCellFieldComingFromPatch
1221 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) const
1223 if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1224 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
1225 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1226 MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
1230 * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is
1231 * defined by ghostLev.
1233 * \param [in] patchId - the id of the considered patch.
1234 * \param [in] ghostLev - the size of the neighborhood.
1235 * \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.
1237 DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const
1239 int nbp(getNumberOfPatches());
1240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1241 for(int i=0;i<nbp;i++)
1244 if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1245 ret->pushBackSilent(i);
1250 MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
1252 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1253 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1254 std::vector<int> cgs(_mesh->getCellGridStructure());
1255 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
1257 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1259 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1260 msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
1262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1263 msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1264 std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
1265 for(std::size_t i=0;i<msSafe.size();i++)
1267 return MEDCouplingUMesh::MergeUMeshes(ms);
1271 * This method returns a mesh containing as cells that there is patches at the current level.
1272 * The patches are seen like 'boxes' that is too say the refinement will not appear here.
1274 * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
1276 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
1278 std::vector<const MEDCoupling1SGTUMesh *> cells;
1279 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
1280 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1282 const MEDCouplingCartesianAMRPatch *patch(*it);
1285 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
1286 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
1287 cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
1290 return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
1293 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
1295 std::vector<const MEDCoupling1SGTUMesh *> patches;
1296 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > patchesSafe;
1297 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1299 const MEDCouplingCartesianAMRPatch *patch(*it);
1302 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
1303 patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
1306 return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
1310 * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
1311 * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
1312 * \sa buildUnstructured
1314 MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
1316 if(recurseArrs.empty())
1317 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
1319 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1320 std::vector<int> cgs(_mesh->getCellGridStructure());
1321 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
1323 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1325 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1326 std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
1327 msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
1329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1331 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
1332 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
1333 arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
1334 ret->setArray(arr2);
1335 ret->setName(arr2->getName());
1336 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1337 MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1341 std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
1342 for(std::size_t i=0;i<msSafe.size();i++)
1345 return MEDCouplingFieldDouble::MergeFields(ms);
1349 * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
1350 * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
1352 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const
1354 std::vector<int> st(_mesh->getCellGridStructure());
1355 std::vector< std::pair<int,int> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
1356 std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus<int>(),2*ghostSz));
1357 MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(p,ghostSz);
1358 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
1363 * This method returns all the patches in \a this not equal to \a patchId that are in neighborhood of patch with id \a patchId.
1365 * \sa fillCellFieldOnPatchOnlyGhostAdv
1367 std::vector<int> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(int patchId, int ghostLev) const
1369 std::vector<int> ret;
1370 int nbp(getNumberOfPatches());
1372 for(int i=0;i<nbp;i++)
1375 if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1381 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1382 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
1384 _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1387 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):_father(father)
1390 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : empty father !");
1392 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
1393 mesh->checkCoherency();
1394 _mesh=mesh; _mesh->incrRef();
1397 void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const
1399 int sz(getNumberOfPatches());
1400 if(patchId<0 || patchId>=sz)
1402 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
1403 throw INTERP_KERNEL::Exception(oss.str().c_str());
1407 void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector<int>& factors)
1409 if(getSpaceDimension()!=(int)factors.size())
1410 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !");
1411 if(_factors.empty())
1417 if(_factors!=factors)
1418 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : the factors ");
1422 void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> >& grids) const
1426 const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
1427 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
1428 grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
1432 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1434 const MEDCouplingCartesianAMRPatch *pt(*it);
1437 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> tmp1(*it);
1438 grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
1444 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1446 const MEDCouplingCartesianAMRPatch *pt(*it);
1448 pt->getMesh()->retrieveGridsAtInternal(lev-1,grids);
1453 int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const std::vector<int>& factors)
1456 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !");
1458 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !");
1459 int ghostLevInPatchRef;
1461 ghostLevInPatchRef=0;
1464 ghostLevInPatchRef=(ghostLev-1)/factors[0]+1;
1465 for(std::size_t i=0;i<factors.size();i++)
1466 ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/factors[i]+1);
1468 return ghostLevInPatchRef;
1472 * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
1473 * Elements in \a all are expected to be sorted from god father to most refined structure.
1475 std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
1477 int maxLev(getMaxNumberOfLevelsRelativeToThis());
1478 std::vector<const DataArrayDouble *> ret;
1479 std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
1481 for(int i=0;i<maxLev;i++)
1483 std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
1484 for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
1486 if((*it)==head || head->isObjectInTheProgeny(*it))
1487 ret.push_back(all[kk]);
1489 std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
1490 for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
1492 const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
1493 meshesTmp.push_back(mesh);
1499 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
1503 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
1505 return sizeof(MEDCouplingCartesianAMRMeshGen);
1508 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildren() const
1510 std::vector<const BigMemoryObject *> ret;
1511 if((const MEDCouplingIMesh *)_mesh)
1512 ret.push_back((const MEDCouplingIMesh *)_mesh);
1513 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1515 if((const MEDCouplingCartesianAMRPatch*)*it)
1516 ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
1521 void MEDCouplingCartesianAMRMeshGen::updateTime() const
1523 if((const MEDCouplingIMesh *)_mesh)
1524 updateTimeWith(*_mesh);
1525 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1527 const MEDCouplingCartesianAMRPatch *elt(*it);
1530 const MEDCouplingCartesianAMRMeshGen *mesh(elt->getMesh());
1532 updateTimeWith(*mesh);
1536 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(father,mesh)
1540 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1541 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1543 return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1546 void MEDCouplingCartesianAMRMesh::setData(MEDCouplingDataForGodFather *data)
1548 MEDCouplingDataForGodFather *myData(_data);
1552 myData->changeGodFather(0);
1558 void MEDCouplingCartesianAMRMesh::allocData() const
1564 void MEDCouplingCartesianAMRMesh::deallocData() const
1570 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1571 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
1575 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
1577 std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren());
1578 const MEDCouplingDataForGodFather *pt(_data);
1584 void MEDCouplingCartesianAMRMesh::checkData() const
1586 const MEDCouplingDataForGodFather *data(_data);
1588 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkData : no data set !");
1591 MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()
1593 MEDCouplingDataForGodFather *data(_data);
1595 data->changeGodFather(0);