1 // Copyright (C) 2007-2015 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 MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(const MEDCouplingCartesianAMRPatchGen& other, MEDCouplingCartesianAMRMeshGen *father):RefCountObject(other),_mesh(other._mesh)
60 const MEDCouplingCartesianAMRMeshGen *mesh(other._mesh);
62 _mesh=mesh->deepCpy(father);
65 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
67 const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
69 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe const : the mesh is NULL !");
73 MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
75 MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
77 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe : the mesh is NULL !");
81 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildrenWithNull() const
83 std::vector<const BigMemoryObject *> ret;
84 ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
89 * \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.
90 * \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,
91 * a the end cell (\b excluded) of the range for the second element of the pair.
93 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair<int,int> >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight)
95 int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension());
97 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
100 MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRPatch::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const
102 return new MEDCouplingCartesianAMRPatch(*this,father);
105 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
107 return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
110 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
112 return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
116 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
117 * 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 !).
118 * Call isInMyNeighborhoodExt to deal with 2 patches not sharing directly the same father.
120 * \param [in] other - The other patch
121 * \param [in] ghostLev - The size of the neighborhood zone.
123 * \throw if \a this or \a other are invalid (end before start).
124 * \throw if \a ghostLev is \b not >= 0 .
125 * \throw if \a this and \a other have not the same space dimension.
127 * \sa isInMyNeighborhoodExt
129 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
132 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !");
134 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !");
135 const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
136 const std::vector< std::pair<int,int> >& otherp(other->getBLTRRange());
137 return IsInMyNeighborhood(ghostLev==0?0:1,thisp,otherp);//make hypothesis that nb this->_mesh->getFather->getFactors() is >= ghostLev
141 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
142 * 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
143 * ancestor must be the same. If they don't have the same ancestor an exception will be thrown.
145 * \param [in] other - The other patch
146 * \param [in] ghostLev - The size of the neighborhood zone.
148 * \throw if \a this or \a other are invalid (end before start).
149 * \throw if \a ghostLev is \b not >= 0 .
150 * \throw if \a this and \a other have not the same space dimension.
151 * \throw if there is not common ancestor of \a this and \a other.
153 * \sa isInMyNeighborhood, isInMyNeighborhoodDiffLev
155 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
158 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the size of the neighborhood must be >= 0 !");
160 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the input patch is NULL !");
162 const MEDCouplingCartesianAMRMeshGen *com(FindCommonAncestor(this,other,lev));//check that factors are OK
164 return isInMyNeighborhood(other,ghostLev);
165 std::vector<int> offset(ComputeOffsetFromTwoToOne(com,lev,this,other));
166 const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
167 std::vector< std::pair<int,int> > otherp(other->getBLTRRange());
168 otherp=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp,offset);
169 return IsInMyNeighborhood(ghostLev,thisp,otherp);
173 * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
174 * the must be >= 0. This method works even if \a this and \a other does not share the same father.
175 * \a this is expected to be more refined than \a other. That is to say lev of \a this is greater than level of \a other.
177 * \param [in] other - The other patch
178 * \param [in] ghostLev - The size of the neighborhood zone.
180 * \throw if \a this or \a other are invalid (end before start).
181 * \throw if \a ghostLev is \b not >= 0 .
182 * \throw if \a this and \a other have not the same space dimension.
183 * \throw if there is not common ancestor of \a this and \a other.
185 * \sa isInMyNeighborhoodExt
187 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
189 std::vector< std::pair<int,int> > thispp,otherpp;
190 std::vector<int> factors;
191 ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,this,other,thispp,otherpp,factors);
192 return IsInMyNeighborhood(ghostLev>0?1:0,thispp,otherpp);//1 not ghostLev ! It is not a bug ( I hope :) ) ! Because as \a this is a refinement of \a other ghostLev is supposed to be <= factors
195 std::vector< std::pair<int,int> > MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF() const
197 std::vector< std::pair<int,int> > ret(_bl_tr);
198 const MEDCouplingCartesianAMRMeshGen *mesh(getMesh());
200 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF : not valid !");
201 const MEDCouplingCartesianAMRMeshGen *fath(mesh->getFather());
203 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF : not valid 2 !");
204 std::vector<int> factors(fath->getFactors());
205 std::size_t sz(ret.size());
206 for(std::size_t ii=0;ii<sz;ii++)
208 ret[ii].first*=factors[ii];
209 ret[ii].second*=factors[ii];
211 const MEDCouplingCartesianAMRMeshGen *oldFather(fath);
212 fath=oldFather->getFather();
215 int pos(fath->getPatchIdFromChildMesh(oldFather));
216 const MEDCouplingCartesianAMRPatch *p(fath->getPatch(pos));
217 const std::vector< std::pair<int,int> >& tmp(p->getBLTRRange());
218 const std::vector<int>& factors2(fath->getFactors());
219 std::transform(factors.begin(),factors.end(),factors2.begin(),factors.begin(),std::multiplies<int>());
220 for(std::size_t ii=0;ii<sz;ii++)
222 int delta(ret[ii].second-ret[ii].first);
223 ret[ii].first+=tmp[ii].first*factors[ii];
224 ret[ii].second=ret[ii].first+delta;
227 fath=oldFather->getFather();
232 std::vector<int> MEDCouplingCartesianAMRPatch::computeCellGridSt() const
234 const MEDCouplingCartesianAMRMeshGen *m(getMesh());
236 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no mesh held by this !");
237 const MEDCouplingCartesianAMRMeshGen *father(m->getFather());
239 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no father help by underlying mesh !");
240 const std::vector< std::pair<int,int> >& bltr(getBLTRRange());
241 const std::vector<int>& factors(father->getFactors());
242 std::vector<int> ret(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(bltr));
243 std::transform(ret.begin(),ret.end(),factors.begin(),ret.begin(),std::multiplies<int>());
247 bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::vector< std::pair<int,int> >& p1, const std::vector< std::pair<int,int> >& p2)
249 std::size_t thispsize(p1.size());
250 if(thispsize!=p2.size())
251 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !");
252 for(std::size_t i=0;i<thispsize;i++)
254 const std::pair<int,int>& thispp(p1[i]);
255 const std::pair<int,int>& otherpp(p2[i]);
256 if(thispp.second<thispp.first)
257 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
258 if(otherpp.second<otherpp.first)
259 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
260 if(otherpp.first==thispp.second+ghostLev-1)
262 if(otherpp.second+ghostLev-1==thispp.first)
264 int start(std::max(thispp.first,otherpp.first)),end(std::min(thispp.second,otherpp.second));
272 * \sa FindNeighborsOfSubPatchesOf
274 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
277 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev : the input pointers must be not NULL !");
278 std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > ret;
279 std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()),p2Work(p2->getMesh()->getPatches());
280 while(!p1Work.empty())
282 std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > retTmp;
283 std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2,p2Work2;
284 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it1=p1Work.begin();it1!=p1Work.end();it1++)
286 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
288 if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev>0?1:0))//1 not ghostLev ! It is not a bug ( I hope :) ) ! Because as \a this is a refinement of \a other ghostLev is supposed to be <= factors
289 retTmp.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it1,*it2));
291 std::vector<const MEDCouplingCartesianAMRPatch *> tmp1((*it1)->getMesh()->getPatches());
292 p1Work2.insert(p1Work2.end(),tmp1.begin(),tmp1.end());
294 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
296 std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it2)->getMesh()->getPatches());
297 p2Work2.insert(p2Work2.end(),tmp2.begin(),tmp2.end());
299 ret.push_back(retTmp);
307 * This method returns all pair of patches (pa,pb) so that pb is in the neighborhood of pa (size of neighborhood is \a ghostLev).
308 * 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
309 * FindNeighborsOfSubPatchesOfSameLev.
311 * \sa FindNeighborsOfSubPatchesOfSameLev
313 void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<const MEDCouplingCartesianAMRPatch *, const MEDCouplingCartesianAMRPatch *> >& ret)
316 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf : the input pointers must be not NULL !");
317 std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches());
318 while(!p1Work.empty())
320 std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2;
321 for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it0=p1Work.begin();it0!=p1Work.end();it0++)
323 if((*it0)->isInMyNeighborhoodDiffLev(p2,ghostLev))
324 ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it0,p2));
325 std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it0)->getMesh()->getPatches());
326 p1Work2.insert(p1Work2.end(),tmp2.begin(),tmp2.end());
333 * \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.
335 * \saUpdateNeighborsOfOneWithTwoExt
337 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int ghostLev, const std::vector<int>& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
339 const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());
340 const std::vector< std::pair<int,int> >& p2BLTR(p2->getBLTRRange());
341 UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2);
345 * Idem than UpdateNeighborsOfOneWithTwo, except that here \a p1 and \a p2 are not sharing the same direct father.
347 * \sa UpdateNeighborsOfOneWithTwo
349 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
351 const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)]
352 std::vector< std::pair<int,int> > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)]
354 const MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev));
355 std::vector<int> offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4]
356 p2BLTR=MEDCouplingStructuredMesh::TranslateCompactFrmt(p2BLTR,offset);//p2BLTR=[(12,13),(4,9)]
357 UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1BLTR,p2BLTR,dataOnP1,dataOnP2);
361 * \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 !
363 void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2, bool isConservative)
365 std::vector< std::pair<int,int> > p1pp,p2pp;
366 std::vector<int> factors;
367 ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,p1,p2,p1pp,p2pp,factors);
369 std::vector<int> dimsP2NotRefined(p2->computeCellGridSt());
370 std::vector<int> dimsP2Refined(dimsP2NotRefined);
371 std::transform(dimsP2NotRefined.begin(),dimsP2NotRefined.end(),factors.begin(),dimsP2Refined.begin(),std::multiplies<int>());
372 std::vector< std::pair<int,int> > p2RefinedAbs(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsP2NotRefined));
373 std::vector<int> dimsP2RefinedGhost(dimsP2Refined.size());
374 std::transform(dimsP2Refined.begin(),dimsP2Refined.end(),dimsP2RefinedGhost.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));
375 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents());
376 MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev);
379 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(factors));
380 std::transform(fineP2->begin(),fineP2->end(),fineP2->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
383 UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1pp,p2pp,dataOnP1,fineP2);
387 * \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 !
388 * 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
389 * on the same level as \a p1.
391 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)
393 std::vector<const MEDCouplingCartesianAMRMeshGen *> ancestorsOfThis;
394 const MEDCouplingCartesianAMRMeshGen *work(p1->getMesh()),*work2(0);
395 ancestorsOfThis.push_back(work);
398 work=work->getFather();
400 ancestorsOfThis.push_back(work);
405 std::size_t levThis(0),levOther(0);
406 while(work && !found)
409 work=work->getFather();
413 std::vector<const MEDCouplingCartesianAMRMeshGen *>::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work));
414 if(it!=ancestorsOfThis.end())
416 levThis=std::distance(ancestorsOfThis.begin(),it);
422 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : no common ancestor found !");
423 if(levThis<=levOther)
424 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : this method is not called correctly !");
426 const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]);
427 int idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2));
428 const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther));
429 std::vector<int> offset(ComputeOffsetFromTwoToOne(comAncestor,levOther,thisp,otherp));
430 p1Zone=thisp->getBLTRRange(); p2Zone=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset);
431 factToApplyOn2.resize(p1Zone.size()); std::fill(factToApplyOn2.begin(),factToApplyOn2.end(),1);
433 std::size_t nbOfTurn(levThis-levOther);
434 for(std::size_t i=0;i<nbOfTurn;i++)
436 std::vector< std::pair<int,int> > tmp0;
437 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1Zone,p2Zone,tmp0,false);
439 const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]);
440 ApplyFactorsOnCompactFrmt(p2Zone,curAncestor->getFactors());
441 curAncestor=ancestorsOfThis[levThis-1-i];
442 const std::vector<int>& factors(curAncestor->getFactors());
443 std::transform(factToApplyOn2.begin(),factToApplyOn2.end(),factors.begin(),factToApplyOn2.begin(),std::multiplies<int>());
444 int tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i]));
445 p1Zone=curAncestor->getPatch(tmpId)->getBLTRRange();
449 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
451 std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
452 ret+=_bl_tr.capacity()*sizeof(std::pair<int,int>);
456 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, int& lev)
458 const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
460 while(f1!=f2 || f1==0 || f2==0)
462 f1=f1->getFather(); f2=f2->getFather();
463 if(f1->getFactors()!=f2->getFactors())
464 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : factors differ !");
468 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : no common ancestor between p1 and p2 !");
472 std::vector<int> MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, int lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
475 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : this method is useful only for lev > 0 !");
477 int dim(p1->getMesh()->getSpaceDimension());
478 if(p2->getMesh()->getSpaceDimension()!=dim)
479 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : dimension must be the same !");
480 std::vector< int > ret(dim,0);
481 for(int i=0;i<zeLev;i++)
483 const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
484 const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0);
485 for(int j=0;j<lev-i;j++)
487 const MEDCouplingCartesianAMRMeshGen *f1tmp(f1->getFather()),*f2tmp(f2->getFather());
488 int pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2));
489 p1h=f1tmp->getPatch(pid1); p2h=f2tmp->getPatch(pid2);
492 std::vector< std::pair<int,int> > p2c(p2h->getBLTRRange());
493 for(int k=0;k<dim;k++)
495 p2c[k].first+=ret[k];
496 p2c[k].second+=ret[k];
498 for(int k=0;k<dim;k++)
500 ret[k]=p2c[k].first-p1h->getBLTRRange()[k].first;
501 ret[k]*=f1->getFactors()[k];
507 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)
508 {//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)]
509 int dim((int)factors.size());
510 std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2]
511 std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
512 std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
513 std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
514 std::vector<int> fakeFactors(dim,1);
516 std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
517 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)]
518 ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)]
519 MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
520 std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
521 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)]
522 ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)]
523 MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
525 std::vector< std::pair<int,int> > dimsFine(p2);
526 ApplyFactorsOnCompactFrmt(dimsFine,factors);
527 ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
529 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
530 MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1);
533 MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(const MEDCouplingCartesianAMRPatch& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father),_bl_tr(other._bl_tr)
538 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
539 * \param [in] factors - the factors per axis.
541 void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
543 std::size_t sz(factors.size());
544 if(sz!=partBeforeFact.size())
545 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
546 for(std::size_t i=0;i<sz;i++)
548 partBeforeFact[i].first*=factors[i];
549 partBeforeFact[i].second*=factors[i];
554 * This method is different than ApplyGhostOnCompactFrmt. The \a partBeforeFact parameter is enlarger contrary to ApplyGhostOnCompactFrmt.
556 * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
557 * \param [in] ghostSize - the ghost size of zone for all axis.
559 void MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
562 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
563 std::size_t sz(partBeforeFact.size());
564 for(std::size_t i=0;i<sz;i++)
566 partBeforeFact[i].first-=ghostSize;
567 partBeforeFact[i].second+=ghostSize;
571 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
575 MEDCouplingCartesianAMRPatchGF *MEDCouplingCartesianAMRPatchGF::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const
577 return new MEDCouplingCartesianAMRPatchGF(*this,father);
580 std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
582 return sizeof(MEDCouplingCartesianAMRPatchGF);
585 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father)
591 int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const
593 return _mesh->getSpaceDimension();
596 void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFactors)
598 if(getSpaceDimension()!=(int)newFactors.size())
599 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : size of input factors is not equal to the space dimension !");
605 if(_factors==newFactors)
607 if(!_patches.empty())
608 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : modification of factors is not allowed when presence of patches !");
613 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
616 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
617 ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
622 * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this.
623 * The patches in \a this are ignored here.
624 * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap
626 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
628 return _mesh->getNumberOfCells();
632 * 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
633 * to take into account of the ghost cells for future computation.
634 * The patches in \a this are ignored here.
636 * \sa getNumberOfCellsAtCurrentLevel
638 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
640 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
641 return tmp->getNumberOfCells();
645 * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels
646 * starting from this. The set of cells which size is returned here are generally overlapping each other.
648 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
650 int ret(_mesh->getNumberOfCells());
651 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
653 ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
659 * This method returns the max number of cells covering all the space without overlapping.
660 * It returns the number of cells of the mesh with the highest resolution.
661 * The returned value is equal to the number of cells of mesh returned by buildUnstructured.
663 * \sa buildUnstructured
665 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
667 int ret(_mesh->getNumberOfCells());
668 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
670 ret-=(*it)->getNumberOfOverlapedCellsForFather();
671 ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
677 * This method returns a vector of size equal to getAbsoluteLevelRelativeTo. It allows to find position an absolute position of \a this
678 * relative to \a ref (that is typically the god father).
680 * \sa getPatchAtPosition
682 std::vector<int> MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
685 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo : input pointer is NULL !");
686 std::vector<int> ret;
687 getPositionRelativeToInternal(ref,ret);
688 std::reverse(ret.begin(),ret.end());
693 * \sa getPositionRelativeTo, getMeshAtPosition
695 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatchAtPosition(const std::vector<int>& pos) const
697 std::size_t sz(pos.size());
699 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : empty input -> no patch by definition !");
701 const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId));
704 if(!elt || !elt->getMesh())
705 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !");
706 std::vector<int> pos2(pos.begin()+1,pos.end());
707 return elt->getMesh()->getPatchAtPosition(pos2);
710 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getMeshAtPosition(const std::vector<int>& pos) const
712 std::size_t sz(pos.size());
716 const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId));
720 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getMeshAtPosition : NULL patch !");
721 return elt->getMesh();
723 if(!elt || !elt->getMesh())
724 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !");
725 std::vector<int> pos2(pos.begin()+1,pos.end());
726 return elt->getMesh()->getMeshAtPosition(pos2);
730 * This method returns grids relative to god father to specified level \a absoluteLev.
732 * \return std::vector<MEDCouplingCartesianAMRPatchGen *> - objects in vector are to be managed (decrRef) by the caller.
734 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(int absoluteLev) const
737 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !");
738 return getGodFather()->retrieveGridsAt(absoluteLev);
742 * \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,
743 * a the end cell (\b excluded) of the range for the second element of the pair.
744 * \param [in] factors The factor of refinement per axis (different from 0).
746 void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
748 checkFactorsAndIfNotSetAssign(factors);
749 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
750 mesh->refineWithFactor(factors);
751 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
752 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
753 _patches.push_back(elt);
759 class InternalPatch : public RefCountObjectOnly
762 InternalPatch():_nb_of_true(0) { }
763 int getDimension() const { return (int)_part.size(); }
764 double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); }
765 int getNumberOfCells() const { return (int)_crit.size(); }
766 void setNumberOfTrue(int nboft) { _nb_of_true=nboft; }
767 std::vector<bool>& getCriterion() { return _crit; }
768 const std::vector<bool>& getConstCriterion() const { return _crit; }
769 void setPart(const std::vector< std::pair<int,int> >& part) { _part=part; }
770 std::vector< std::pair<int,int> >& getPart() { return _part; }
771 const std::vector< std::pair<int,int> >& getConstPart() const { return _part; }
772 bool presenceOfTrue() const { return _nb_of_true>0; }
773 std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
774 std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
775 double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
776 void zipToFitOnCriterion(int minPatchLgth);
777 void updateNumberOfTrue() const;
778 MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
779 MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
783 mutable int _nb_of_true;
784 std::vector<bool> _crit;
786 std::vector< std::pair<int,int> > _part;
789 void InternalPatch::zipToFitOnCriterion(int minPatchLgth)
791 std::vector<int> cgs(computeCGS());
792 std::vector<bool> newCrit;
793 std::vector< std::pair<int,int> > newPart,newPart2;
794 int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(minPatchLgth,cgs,_crit,newCrit,newPart));
795 MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
796 if(newNbOfTrue!=_nb_of_true)
797 throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
798 _crit=newCrit; _part=newPart2;
801 void InternalPatch::updateNumberOfTrue() const
803 _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
806 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
808 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
809 std::vector<int> cgs(computeCGS());
810 std::vector< std::pair<int,int> > newPart;
811 MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
812 MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion());
813 ret->setPart(partInGlobal);
814 ret->updateNumberOfTrue();
818 MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
820 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
825 void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int largestLength, int& cutPlace)
827 int minimumPatchLength(bso.getMinimumPatchLength());
828 std::vector<double> ratio(largestLength-minimumPatchLength,std::numeric_limits<double>::max());
830 double minSemiEfficiencyRatio(std::numeric_limits<double>::max());
831 double efficiencyPerAxis[2];
833 for(int i=minimumPatchLength-1;i<largestLength-minimumPatchLength;i++)
837 std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
839 rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+i;
841 rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+i;
842 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
843 p->zipToFitOnCriterion(bso.getMinimumPatchLength());
844 efficiencyPerAxis[h]=p->getEfficiencyPerAxis(axisId);
846 ratio[i]=std::max(efficiencyPerAxis[0], efficiencyPerAxis[1]) / std::min(efficiencyPerAxis[0], efficiencyPerAxis[1]);
847 if(ratio[i]<minSemiEfficiencyRatio)
849 minSemiEfficiencyRatio = ratio[i];
855 throw INTERP_KERNEL::Exception("DissectBigPatch : just call to Arthur !");
857 cutPlace=index_min+patchToBeSplit->getConstPart()[axisId].first;
860 bool FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int& cutPlace)
863 int minimumPatchLength(bso.getMinimumPatchLength());
864 const int dim(patchToBeSplit->getDimension());
865 std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
866 for(int id=0;id<dim;id++)
868 const std::vector<int>& signature(signatures[id]);
869 std::vector<int> hole;
870 std::vector<double> distance;
871 int len((int)signature.size());
872 for(int i=minimumPatchLength-1;i<len-minimumPatchLength;i++)
877 int closestHoleToMiddle(hole[0]);
878 int oldDistanceToMiddle(std::abs(hole[0]-len/2));
879 int newDistanceToMiddle(oldDistanceToMiddle);
880 for(std::size_t i=0;i<hole.size();i++)
882 newDistanceToMiddle=std::abs(hole[i]-len/2);
883 if(newDistanceToMiddle < oldDistanceToMiddle)
885 oldDistanceToMiddle = newDistanceToMiddle;
886 closestHoleToMiddle = hole[i];
889 cutPlace=closestHoleToMiddle+patchToBeSplit->getConstPart()[axisId].first;
896 bool FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& cutPlace, int& axisId)
898 bool cutFound(false); cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
899 const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
900 int sign,minimumPatchLength(bso.getMinimumPatchLength());
901 const int dim(patchToBeSplit->getDimension());
903 std::vector<int> zeroCrossDims(dim,-1);
904 std::vector<int> zeroCrossVals(dim,-1);
905 std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
906 for (int id=0;id<dim;id++)
908 const std::vector<int>& signature(signatures[id]);
910 std::vector<int> derivate_second_order,gradient_absolute,zero_cross,edge,max_cross_list ;
911 std::vector<double> distance ;
913 for(std::size_t i=1;i<signature.size()-1;i++)
914 derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
916 // Gradient absolute value
917 for(std::size_t i=1;i<derivate_second_order.size();i++)
918 gradient_absolute.push_back(abs(derivate_second_order[i]-derivate_second_order[i-1])) ;
919 if(derivate_second_order.empty())
921 for(std::size_t i=1;i<derivate_second_order.size()-1;i++)
923 if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
925 if (derivate_second_order[i]*derivate_second_order[i+1] > 0 )
927 if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
929 if ( sign==0 || sign==-1 )
930 if ( i >= (std::size_t)minimumPatchLength-2 && i <= signature.size()-minimumPatchLength-2 )
932 zero_cross.push_back(i) ;
933 edge.push_back(gradient_absolute[i]) ;
936 if ( zero_cross.size() > 0 )
938 int max_cross=*max_element(edge.begin(),edge.end()) ;
939 for (unsigned int i=0;i<edge.size();i++)
940 if (edge[i]==max_cross)
941 max_cross_list.push_back(zero_cross[i]+1) ;
943 double center((signature.size()/2.0));
944 for (unsigned int i=0;i<max_cross_list.size();i++)
945 distance.push_back(fabs(max_cross_list[i]+1-center));
947 double distance_min=*min_element(distance.begin(),distance.end()) ;
948 int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
949 int best_place = max_cross_list[pos_distance_min] + part[id].first ;
952 zeroCrossDims[id] = best_place ;
953 zeroCrossVals[id] = max_cross ;
956 derivate_second_order.clear() ;
957 gradient_absolute.clear() ;
960 max_cross_list.clear() ;
964 if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1 )
966 int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ;
968 if (zeroCrossVals[0]==max_cross_dims && zeroCrossVals[1]==max_cross_dims )
970 int nl_left(part[0].second-part[0].first);
971 int nc_left(part[1].second-part[1].first);
972 if ( nl_left >= nc_left )
978 max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin();
980 cutPlace=zeroCrossDims[max_cross_dims];
981 axisId=max_cross_dims ;
986 bool TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, int& cutPlace)
988 if(patchToBeSplit->getEfficiency()<=bso.getEfficiencyGoal())
990 if(rangeOfAxisId>=2*bso.getMinimumPatchLength())
992 cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
999 if(patchToBeSplit->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || rangeOfAxisId>bso.getMaximumPatchLength())
1001 DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutPlace);
1009 MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
1011 MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
1016 void DealWithCut(double minPatchLgth, const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
1018 MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
1019 std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
1020 std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
1021 leftRect[axisId].second=cutPlace+1;
1022 rightRect[axisId].first=cutPlace+1;
1023 leftPart=patchToBeSplit->extractPart(leftRect);
1024 rightPart=patchToBeSplit->extractPart(rightRect);
1025 leftPart->zipToFitOnCriterion(minPatchLgth); rightPart->zipToFitOnCriterion(minPatchLgth);
1026 listOfPatches.push_back(leftPart);
1027 listOfPatches.push_back(rightPart);
1032 void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
1038 void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
1040 checkPatchId(patchId);
1041 int sz((int)_patches.size()),j(0);
1042 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
1043 for(int i=0;i<sz;i++)
1045 patches[j++]=_patches[i];
1046 (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
1051 int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
1053 return (int)_patches.size();
1057 * This method is a generic algorithm to create patches in \a this (by destroying the patches if any).
1058 * This method uses \a criterion array as a field on cells on this level.
1059 * This method only create patches at level 0 relative to \a this.
1061 * This generic algorithm can be degenerated into three child ones, depending on the arguments given; in particular depending
1062 * on whether they are equal to 0 or not.
1063 * 1/ If minimumPatchLength = maximumPatchLength = maximumPatchVolume = 0, then we have the Berger-Rigoutsos algorithm.
1064 * This algorithm was developed in 1991 and seems appropriate for sequential programming.
1065 * 2/ If maximumPatchLength = 0, then we have the Livne algorithm.
1066 * This algorithm was developed in 2004 and is an improvement of the Berger-Rigoutsos algorithm.
1067 * 3/ If maximumPatchVolume = 0, the we have the lmin-lmax algorithm.
1068 * This algorithm was developed by Arthur TALPAERT in 2014 and is an improvement of the Livne algorithm. It is especially
1069 * appropriate for parallel computing, where one patch would be given to one CPU. See Arthur TALPAERT's 2014 CANUM poster
1070 * for more information.
1073 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
1075 int nbCells(getNumberOfCellsAtCurrentLevel());
1076 if(nbCells!=(int)criterion.size())
1077 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
1079 std::vector<int> cgs(_mesh->getCellGridStructure());
1080 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
1082 MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
1083 p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(bso.getMinimumPatchLength(),cgs,criterion,p->getCriterion(),p->getPart()));
1084 if(p->presenceOfTrue())
1085 listOfPatches.push_back(p);
1086 while(!listOfPatches.empty())
1088 std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
1089 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
1092 int axisId,largestLength,cutPlace;
1093 MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,largestLength);
1094 if((*it)->getEfficiency()>=bso.getEfficiencyThreshold() && ((*it)->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || largestLength>bso.getMaximumPatchLength()))
1096 DissectBigPatch(bso,*it,axisId,largestLength,cutPlace);
1097 DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp);
1100 if(FindHole(bso,*it,axisId,cutPlace))//axisId overwritten here if FindHole equal to true !
1101 { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
1102 if(FindInflection(bso,*it,cutPlace,axisId))//axisId overwritten here if cutFound equal to true !
1103 { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
1104 if(TryAction4(bso,*it,axisId,largestLength,cutPlace))
1105 { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
1107 listOfPatchesOK.push_back(DealWithNoCut(*it));
1109 listOfPatches=listOfPatchesTmp;
1111 for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
1112 addPatch((*it)->getConstPart(),factors);
1117 * 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.
1118 * This method only create patches at level 0 relative to \a this.
1120 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
1122 if(!criterion || !criterion->isAllocated())
1123 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
1124 std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
1125 createPatchesFromCriterion(bso,crit,factors);
1129 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayDouble *criterion, const std::vector<int>& factors, double eps)
1132 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : null criterion pointer !");
1133 std::vector<bool> inp(criterion->toVectorOfBool(eps));
1134 createPatchesFromCriterion(bso,inp,factors);
1137 int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
1140 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
1142 if((*it)->getMesh()==mesh)
1145 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
1148 std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
1150 std::size_t sz(_patches.size());
1151 std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
1152 for(std::size_t i=0;i<sz;i++)
1157 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const
1159 checkPatchId(patchId);
1160 return _patches[patchId];
1164 * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1).
1165 * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !).
1167 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
1169 const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
1170 return p1->isInMyNeighborhood(p2,ghostLev);
1174 * 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.
1175 * 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
1176 * defined by the patch with id \a patchId.
1178 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1179 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1180 * \return DataArrayDouble * - The array of the cell field on the requested patch
1182 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1183 * \throw if \a cellFieldOnThis is NULL or not allocated
1184 * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine
1186 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const
1188 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1189 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1190 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1191 const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
1192 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
1193 ret->copyStringInfoFrom(*cellFieldOnThis);
1194 MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
1199 * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of creating a new instance
1200 * it fills the value into the \a cellFieldOnPatch data.
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.
1206 * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
1208 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, bool isConservative) const
1210 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1211 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
1212 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1213 MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
1216 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1217 std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
1222 * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the
1223 * potential neighbor patches covered by the ghost cells of patch with id \a patchId.
1225 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1226 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1227 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1228 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1230 * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
1232 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev, bool isConservative) const
1234 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1235 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
1236 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1237 MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1240 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1241 std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
1246 * This method is equivalent to fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
1247 * in \a cellFieldOnPatch.
1249 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1250 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1251 * \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.
1252 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1254 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
1256 if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
1257 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
1258 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1259 MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
1263 * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
1264 * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
1266 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1267 * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
1268 * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
1269 * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
1270 * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
1272 * \sa fillCellFieldOnPatchOnlyGhostAdv
1274 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches, bool isConservative) const
1276 int nbp(getNumberOfPatches());
1277 if(nbp!=(int)arrsOnPatches.size())
1279 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1280 throw INTERP_KERNEL::Exception(oss.str().c_str());
1282 DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1283 // first, do as usual
1284 fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev,isConservative);
1285 fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
1289 * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
1290 * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
1292 * \sa getPatchIdsInTheNeighborhoodOf
1294 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
1296 int nbp(getNumberOfPatches());
1297 if(nbp!=(int)arrsOnPatches.size())
1299 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
1300 throw INTERP_KERNEL::Exception(oss.str().c_str());
1302 const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
1303 DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
1304 std::vector<int> ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
1305 for(std::vector<int>::const_iterator it=ids.begin();it!=ids.end();it++)
1307 const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it));
1308 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]);
1312 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const
1314 MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor);
1318 * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
1320 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1321 * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1322 * \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.
1323 * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
1325 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1326 * \throw if \a cellFieldOnPatch is NULL or not allocated
1327 * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
1329 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, bool isConservative) const
1331 if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1332 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
1333 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1334 MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
1337 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1338 MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis);
1343 * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this
1344 * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch.
1346 * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
1347 * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
1348 * \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.
1349 * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
1350 * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
1352 * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
1353 * \throw if \a cellFieldOnPatch is NULL or not allocated
1354 * \sa fillCellFieldComingFromPatch
1356 void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev, bool isConservative) const
1358 if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
1359 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
1360 const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
1361 MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
1364 int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
1365 MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis);
1370 * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is
1371 * defined by ghostLev.
1373 * \param [in] patchId - the id of the considered patch.
1374 * \param [in] ghostLev - the size of the neighborhood.
1375 * \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.
1377 DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const
1379 int nbp(getNumberOfPatches());
1380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
1381 for(int i=0;i<nbp;i++)
1384 if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1385 ret->pushBackSilent(i);
1390 MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
1392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1393 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1394 std::vector<int> cgs(_mesh->getCellGridStructure());
1395 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
1397 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1399 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1400 msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
1402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1403 msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1404 std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
1405 for(std::size_t i=0;i<msSafe.size();i++)
1407 return MEDCouplingUMesh::MergeUMeshes(ms);
1411 * This method returns a mesh containing as cells that there is patches at the current level.
1412 * The patches are seen like 'boxes' that is too say the refinement will not appear here.
1414 * \return MEDCoupling1SGTUMesh * - A new object to be managed by the caller containing as cells as there are patches in \a this.
1416 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
1418 std::vector<const MEDCoupling1SGTUMesh *> cells;
1419 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
1420 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1422 const MEDCouplingCartesianAMRPatch *patch(*it);
1425 MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
1426 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
1427 cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
1430 return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(cells);
1433 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
1435 std::vector<const MEDCoupling1SGTUMesh *> patches;
1436 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > patchesSafe;
1437 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1439 const MEDCouplingCartesianAMRPatch *patch(*it);
1442 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
1443 patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
1446 return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
1450 * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
1451 * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
1452 * \sa buildUnstructured
1454 MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
1456 if(recurseArrs.empty())
1457 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
1459 std::vector<bool> bs(_mesh->getNumberOfCells(),false);
1460 std::vector<int> cgs(_mesh->getCellGridStructure());
1461 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
1463 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
1465 MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
1466 std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
1467 msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
1469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
1471 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
1472 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
1473 arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
1474 ret->setArray(arr2);
1475 ret->setName(arr2->getName());
1476 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
1477 MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
1481 std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
1482 for(std::size_t i=0;i<msSafe.size();i++)
1485 return MEDCouplingFieldDouble::MergeFields(ms);
1489 * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
1490 * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
1492 DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const
1494 std::vector<int> st(_mesh->getCellGridStructure());
1495 std::vector< std::pair<int,int> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
1496 std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus<int>(),2*ghostSz));
1497 MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz);
1498 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
1503 * This method returns all the patches in \a this not equal to \a patchId that are in neighborhood of patch with id \a patchId.
1505 * \sa fillCellFieldOnPatchOnlyGhostAdv
1507 std::vector<int> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(int patchId, int ghostLev) const
1509 std::vector<int> ret;
1510 int nbp(getNumberOfPatches());
1512 for(int i=0;i<nbp;i++)
1515 if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
1522 * This method returns a dump python of \a this. It is useful for users of createPatchesFromCriterion method for debugging.
1524 * \sa dumpPatchesOf, createPatchesFromCriterion, createPatchesFromCriterionML
1526 std::string MEDCouplingCartesianAMRMeshGen::buildPythonDumpOfThis() const
1528 std::ostringstream oss;
1529 oss << "amr=MEDCouplingCartesianAMRMesh(\""<< getImageMesh()->getName() << "\"," << getSpaceDimension() << ",[";
1530 std::vector<int> ngs(getImageMesh()->getNodeGridStructure());
1531 std::vector<double> orig(getImageMesh()->getOrigin()),dxyz(getImageMesh()->getDXYZ());
1532 std::copy(ngs.begin(),ngs.end(),std::ostream_iterator<int>(oss,","));
1534 std::copy(orig.begin(),orig.end(),std::ostream_iterator<double>(oss,","));
1536 std::copy(dxyz.begin(),dxyz.end(),std::ostream_iterator<double>(oss,","));
1538 dumpPatchesOf("amr",oss);
1542 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const MEDCouplingCartesianAMRMeshGen& other):RefCountObject(other),_mesh(other._mesh),_patches(other._patches),_factors(other._factors)
1544 const MEDCouplingIMesh *mesh(other._mesh);
1546 _mesh=static_cast<MEDCouplingIMesh *>(mesh->deepCpy());
1547 std::size_t sz(other._patches.size());
1548 for(std::size_t i=0;i<sz;i++)
1550 const MEDCouplingCartesianAMRPatch *patch(other._patches[i]);
1552 _patches[i]=patch->deepCpy(this);
1556 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1557 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1559 _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1562 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh)
1565 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
1566 mesh->checkCoherency();
1567 _mesh=mesh; _mesh->incrRef();
1570 void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const
1572 int sz(getNumberOfPatches());
1573 if(patchId<0 || patchId>=sz)
1575 std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !";
1576 throw INTERP_KERNEL::Exception(oss.str().c_str());
1580 void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector<int>& factors)
1582 if(getSpaceDimension()!=(int)factors.size())
1583 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !");
1584 if(_factors.empty())
1590 if(_factors!=factors)
1591 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign : the factors ");
1595 void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> >& grids) const
1599 const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
1600 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
1601 grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
1605 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1607 const MEDCouplingCartesianAMRPatch *pt(*it);
1610 MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> tmp1(*it);
1611 grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
1617 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1619 const MEDCouplingCartesianAMRPatch *pt(*it);
1621 pt->getMesh()->retrieveGridsAtInternal(lev-1,grids);
1626 int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const std::vector<int>& factors)
1629 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !");
1631 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !");
1632 int ghostLevInPatchRef;
1634 ghostLevInPatchRef=0;
1637 ghostLevInPatchRef=(ghostLev-1)/factors[0]+1;
1638 for(std::size_t i=0;i<factors.size();i++)
1639 ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/factors[i]+1);
1641 return ghostLevInPatchRef;
1645 * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
1646 * Elements in \a all are expected to be sorted from god father to most refined structure.
1648 std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
1650 int maxLev(getMaxNumberOfLevelsRelativeToThis());
1651 std::vector<const DataArrayDouble *> ret;
1652 std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
1654 for(int i=0;i<maxLev;i++)
1656 std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
1657 for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
1659 if((*it)==head || head->isObjectInTheProgeny(*it))
1660 ret.push_back(all[kk]);
1662 std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
1663 for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
1665 const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
1666 meshesTmp.push_back(mesh);
1672 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
1676 void MEDCouplingCartesianAMRMeshGen::dumpPatchesOf(const std::string& varName, std::ostream& oss) const
1679 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1681 const MEDCouplingCartesianAMRPatch *patch(*it);
1684 std::ostringstream oss2; oss2 << varName << ".addPatch([";
1685 const std::vector< std::pair<int,int> >& bltr(patch->getBLTRRange());
1686 std::size_t sz(bltr.size());
1687 for(std::size_t i=0;i<sz;i++)
1689 oss2 << "(" << bltr[i].first << "," << bltr[i].second << ")";
1694 std::copy(_factors.begin(),_factors.end(),std::ostream_iterator<int>(oss2,","));
1697 std::ostringstream oss3; oss3 << varName << "[" << j++ << "]";
1698 patch->getMesh()->dumpPatchesOf(oss3.str(),oss);
1703 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
1705 return sizeof(MEDCouplingCartesianAMRMeshGen);
1708 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull() const
1710 std::vector<const BigMemoryObject *> ret;
1711 ret.push_back((const MEDCouplingIMesh *)_mesh);
1712 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1713 ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
1717 void MEDCouplingCartesianAMRMeshGen::updateTime() const
1719 if((const MEDCouplingIMesh *)_mesh)
1720 updateTimeWith(*_mesh);
1721 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
1723 const MEDCouplingCartesianAMRPatch *elt(*it);
1726 const MEDCouplingCartesianAMRMeshGen *mesh(elt->getMesh());
1728 updateTimeWith(*mesh);
1732 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh),_father(father)
1735 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh) constructor : empty father !");
1738 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getFather() const
1743 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getGodFather() const
1746 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getGodFather : Impossible to find a god father because there is a hole in chain !");
1747 return _father->getGodFather();
1751 * This method returns the level of \a this. 0 for god father. 1 for children of god father ...
1753 int MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel() const
1756 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel : Impossible to find a god father because there is a hole in chain !");
1757 return _father->getAbsoluteLevel()+1;
1760 void MEDCouplingCartesianAMRMeshSub::detachFromFather()
1766 std::vector< std::pair<int,int> > MEDCouplingCartesianAMRMeshSub::positionRelativeToGodFather(std::vector<int>& st) const
1768 st=_father->getFactors();
1769 std::size_t dim(st.size());
1770 std::vector<int> prev(st);
1771 int id(_father->getPatchIdFromChildMesh(this));
1772 const MEDCouplingCartesianAMRPatch *p(_father->getPatch(id));
1773 std::vector< std::pair<int,int> > ret(p->getBLTRRange());
1774 std::vector<int> delta(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(ret)),start(dim);
1775 std::transform(delta.begin(),delta.end(),prev.begin(),delta.begin(),std::multiplies<int>());
1776 for(std::size_t i=0;i<dim;i++)
1777 start[i]=ret[i].first;
1778 std::transform(start.begin(),start.end(),prev.begin(),start.begin(),std::multiplies<int>());
1779 const MEDCouplingCartesianAMRMeshGen *it(_father);
1780 while(!dynamic_cast<const MEDCouplingCartesianAMRMesh *>(it))
1782 const MEDCouplingCartesianAMRMeshSub *itc(static_cast<const MEDCouplingCartesianAMRMeshSub *>(it));
1783 int id2(itc->_father->getPatchIdFromChildMesh(itc));
1784 const MEDCouplingCartesianAMRPatch *p2(itc->_father->getPatch(id2));
1785 const std::vector< std::pair<int,int> >& start2(p2->getBLTRRange());
1786 std::vector<int> tmp(dim);
1787 for(std::size_t i=0;i<dim;i++)
1788 tmp[i]=start2[i].first;
1790 prev=itc->_father->getFactors();
1791 std::transform(st.begin(),st.end(),prev.begin(),st.begin(),std::multiplies<int>());
1792 std::transform(st.begin(),st.end(),tmp.begin(),tmp.begin(),std::multiplies<int>());
1793 std::transform(start.begin(),start.end(),tmp.begin(),start.begin(),std::plus<int>());
1796 for(std::size_t i=0;i<dim;i++)
1798 ret[i].first=start[i];
1799 ret[i].second=start[i]+delta[i];
1804 int MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
1809 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
1811 return _father->getAbsoluteLevelRelativeTo(ref)+1;
1814 MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(const MEDCouplingCartesianAMRMeshSub& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRMeshGen(other),_father(father)
1818 MEDCouplingCartesianAMRMeshSub *MEDCouplingCartesianAMRMeshSub::deepCpy(MEDCouplingCartesianAMRMeshGen *fath) const
1820 return new MEDCouplingCartesianAMRMeshSub(*this,fath);
1824 * \sa getPositionRelativeTo
1826 void MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<int>& ret) const
1831 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal : ref is not in the progeny of this !");
1832 int myId(_father->getPatchIdFromChildMesh(this));
1833 ret.push_back(myId);
1834 _father->getPositionRelativeToInternal(ref,ret);
1837 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1838 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
1840 return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
1843 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(MEDCouplingIMesh *mesh)
1845 return new MEDCouplingCartesianAMRMesh(mesh);
1848 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getFather() const
1850 //I'm god father ! No father !
1854 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getGodFather() const
1859 int MEDCouplingCartesianAMRMesh::getAbsoluteLevel() const
1864 void MEDCouplingCartesianAMRMesh::detachFromFather()
1865 {//not a bug - do nothing
1868 std::vector< std::pair<int,int> > MEDCouplingCartesianAMRMesh::positionRelativeToGodFather(std::vector<int>& st) const
1870 st=_mesh->getCellGridStructure();
1871 return MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st);
1874 int MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
1878 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
1881 std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMesh::retrieveGridsAt(int absoluteLev) const
1883 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > rets;
1884 retrieveGridsAtInternal(absoluteLev,rets);
1885 std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
1886 for(std::size_t i=0;i<rets.size();i++)
1888 ret[i]=rets[i].retn();
1893 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const
1896 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::deepCpy : specifying a not null father for a God Father object !");
1897 return new MEDCouplingCartesianAMRMesh(*this);
1901 * This method creates a multi level patches split at once.
1902 * This method calls as times as size of \a bso createPatchesFromCriterion. Size of \a bso and size of \a factors must be the same !
1903 * \b WARNING, after the call the number of levels in \a this is equal to bso.size() + 1 !
1906 * \param [in] criterion
1907 * \param [in] factors
1908 * \param [in] eps - See DataArrayDouble::toVectorOfBool for more information about the semantic of eps.
1910 * \sa createPatchesFromCriterion
1912 void MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML(const std::vector<const INTERP_KERNEL::BoxSplittingOptions *>& bso, const DataArrayDouble *criterion, const std::vector< std::vector<int> >& factors, double eps)
1914 std::size_t nbOfLevs(bso.size());
1915 if(nbOfLevs!=factors.size())
1916 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : size of vectors must be the same !");
1920 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : pointers in 1st arg must be not NULL !");
1921 createPatchesFromCriterion(*bso[0],criterion,factors[0],eps);
1922 for(std::size_t i=1;i<nbOfLevs;i++)
1925 throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : presence of a NULL BoxSplittingOptions in input vector !");
1927 std::vector<MEDCouplingCartesianAMRPatchGen *> elts(retrieveGridsAt((int)(i)));
1928 std::size_t sz(elts.size());
1929 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > elts2(sz);
1930 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > elts3(sz);
1931 for(std::size_t ii=0;ii<sz;ii++)
1934 static const char TMP_STR[]="TMP";
1935 std::vector< std::pair<std::string,int> > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1;
1936 MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> att(MEDCouplingAMRAttribute::New(this,fieldNames,0));
1938 DataArrayDouble *tmpDa(const_cast<DataArrayDouble *>(att->getFieldOn(this,TMP_STR)));
1939 tmpDa->cpyFrom(*criterion);
1940 att->synchronizeCoarseToFine();
1941 for(std::size_t ii=0;ii<sz;ii++)
1943 const DataArrayDouble *critOnLeaf(att->getFieldOn(const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh()),TMP_STR));
1944 elts3[ii]=const_cast<DataArrayDouble *>(critOnLeaf); elts3[ii]->incrRef();
1947 for(std::size_t ii=0;ii<sz;ii++)
1948 const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh())->createPatchesFromCriterion(*bso[i],elts3[ii],factors[i],eps);
1952 void MEDCouplingCartesianAMRMesh::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<int>& ret) const
1957 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const MEDCouplingCartesianAMRMesh& other):MEDCouplingCartesianAMRMeshGen(other)
1961 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
1962 const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
1966 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh)
1970 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildrenWithNull() const
1972 std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull());
1976 MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()