X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingCartesianAMRMesh.cxx;h=719fd48d1cdd34c501ffa612dad6f272671f1e60;hb=04f1c450d57b28c7c473bdc59dc87eeef7393ca5;hp=9a02d7b79685f4a7c5af37a12bdab9288bf9945f;hpb=e8f6d0c2ecb69600ee7cc75a309f266aafd50a1b;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx old mode 100644 new mode 100755 index 9a02d7b79..719fd48d1 --- a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx +++ b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D +// Copyright (C) 2007-2020 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,7 @@ // Author : Anthony Geay #include "MEDCouplingCartesianAMRMesh.hxx" +#include "MEDCouplingAMRAttribute.hxx" #include "MEDCouplingFieldDouble.hxx" #include "MEDCoupling1GTUMesh.hxx" #include "MEDCouplingIMesh.hxx" @@ -28,21 +29,21 @@ #include #include -using namespace ParaMEDMEM; +using namespace MEDCoupling; /// @cond INTERNAL -int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithOverlap() const +mcIdType MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithOverlap() const { return _mesh->getNumberOfCellsRecursiveWithOverlap(); } -int MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithoutOverlap() const +mcIdType MEDCouplingCartesianAMRPatchGen::getNumberOfCellsRecursiveWithoutOverlap() const { return _mesh->getNumberOfCellsRecursiveWithoutOverlap(); } -int MEDCouplingCartesianAMRPatchGen::getMaxNumberOfLevelsRelativeToThis() const +mcIdType MEDCouplingCartesianAMRPatchGen::getMaxNumberOfLevelsRelativeToThis() const { return _mesh->getMaxNumberOfLevelsRelativeToThis(); } @@ -54,6 +55,13 @@ MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCart _mesh=mesh; _mesh->incrRef(); } +MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(const MEDCouplingCartesianAMRPatchGen& other, MEDCouplingCartesianAMRMeshGen *father):RefCountObject(other),_mesh(other._mesh) +{ + const MEDCouplingCartesianAMRMeshGen *mesh(other._mesh); + if(mesh) + _mesh=mesh->deepCopy(father); +} + const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const { const MEDCouplingCartesianAMRMeshGen *mesh(_mesh); @@ -70,11 +78,10 @@ MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() return mesh; } -std::vector MEDCouplingCartesianAMRPatchGen::getDirectChildren() const +std::vector MEDCouplingCartesianAMRPatchGen::getDirectChildrenWithNull() const { std::vector ret; - if((const MEDCouplingCartesianAMRMeshGen *)_mesh) - ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh); + ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh); return ret; } @@ -83,19 +90,24 @@ std::vector MEDCouplingCartesianAMRPatchGen::getDirectC * \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, * a the end cell (\b excluded) of the range for the second element of the pair. */ -MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight) +MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianAMRMeshGen *mesh, const std::vector< std::pair >& bottomLeftTopRight):MEDCouplingCartesianAMRPatchGen(mesh),_bl_tr(bottomLeftTopRight) { - int dim((int)bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension()); + std::size_t dim(bottomLeftTopRight.size()),dimExp(_mesh->getSpaceDimension()); if(dim!=dimExp) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !"); } -void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair >& bottomLeftTopRight, const std::vector& factors) +MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRPatch::deepCopy(MEDCouplingCartesianAMRMeshGen *father) const +{ + return new MEDCouplingCartesianAMRPatch(*this,father); +} + +void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair >& bottomLeftTopRight, const std::vector& factors) { return getMeshSafe()->addPatch(bottomLeftTopRight,factors); } -int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const +mcIdType MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const { return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr); } @@ -114,15 +126,15 @@ int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const * * \sa isInMyNeighborhoodExt */ -bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const +bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, mcIdType ghostLev) const { if(ghostLev<0) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !"); if(!other) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !"); - const std::vector< std::pair >& thisp(getBLTRRange()); - const std::vector< std::pair >& otherp(other->getBLTRRange()); - return IsInMyNeighborhood(ghostLev,thisp,otherp); + const std::vector< std::pair >& thisp(getBLTRRange()); + const std::vector< std::pair >& otherp(other->getBLTRRange()); + return IsInMyNeighborhood(ghostLev==0?0:1,thisp,otherp);//make hypothesis that nb this->_mesh->getFather->getFactors() is >= ghostLev } /*! @@ -140,19 +152,19 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesian * * \sa isInMyNeighborhood, isInMyNeighborhoodDiffLev */ -bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const +bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, mcIdType ghostLev) const { if(ghostLev<0) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the size of the neighborhood must be >= 0 !"); if(!other) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the input patch is NULL !"); - int lev; + mcIdType lev; const MEDCouplingCartesianAMRMeshGen *com(FindCommonAncestor(this,other,lev));//check that factors are OK if(lev==0) return isInMyNeighborhood(other,ghostLev); - std::vector offset(ComputeOffsetFromTwoToOne(com,lev,this,other)); - const std::vector< std::pair >& thisp(getBLTRRange()); - std::vector< std::pair > otherp(other->getBLTRRange()); + std::vector offset(ComputeOffsetFromTwoToOne(com,lev,this,other)); + const std::vector< std::pair >& thisp(getBLTRRange()); + std::vector< std::pair > otherp(other->getBLTRRange()); otherp=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp,offset); return IsInMyNeighborhood(ghostLev,thisp,otherp); } @@ -160,7 +172,7 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartes /*! * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter * the must be >= 0. This method works even if \a this and \a other does not share the same father. - * 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. + * \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. * * \param [in] other - The other patch * \param [in] ghostLev - The size of the neighborhood zone. @@ -172,71 +184,75 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartes * * \sa isInMyNeighborhoodExt */ -bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const +bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, mcIdType ghostLev) const { - std::vector ancestorsOfThis; - const MEDCouplingCartesianAMRMeshGen *work(getMesh()),*work2(0); - ancestorsOfThis.push_back(work); - while(work) + std::vector< std::pair > thispp,otherpp; + std::vector factors; + ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,this,other,thispp,otherpp,factors); + 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 +} + +std::vector< std::pair > MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF() const +{ + std::vector< std::pair > ret(_bl_tr); + const MEDCouplingCartesianAMRMeshGen *mesh(getMesh()); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF : not valid !"); + const MEDCouplingCartesianAMRMeshGen *fath(mesh->getFather()); + if(!fath) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF : not valid 2 !"); + std::vector factors(fath->getFactors()); + std::size_t sz(ret.size()); + for(std::size_t ii=0;iigetFather(); - if(work) - ancestorsOfThis.push_back(work); + ret[ii].first*=factors[ii]; + ret[ii].second*=factors[ii]; } - // - work=other->getMesh(); - bool found(false); - std::size_t levThis(0),levOther(0); - while(work && !found) + const MEDCouplingCartesianAMRMeshGen *oldFather(fath); + fath=oldFather->getFather(); + while(fath) { - work2=work; - work=work->getFather(); - if(work) + mcIdType pos(fath->getPatchIdFromChildMesh(oldFather)); + const MEDCouplingCartesianAMRPatch *p(fath->getPatch(pos)); + const std::vector< std::pair >& tmp(p->getBLTRRange()); + const std::vector& factors2(fath->getFactors()); + std::transform(factors.begin(),factors.end(),factors2.begin(),factors.begin(),std::multiplies()); + for(std::size_t ii=0;ii::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work)); - if(it!=ancestorsOfThis.end()) - { - levThis=std::distance(ancestorsOfThis.begin(),it); - found=true; - } + mcIdType delta(ret[ii].second-ret[ii].first); + ret[ii].first+=tmp[ii].first*factors[ii]; + ret[ii].second=ret[ii].first+delta; } + oldFather=fath; + fath=oldFather->getFather(); } - if(!found) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev : no common ancestor found !"); - if(levThis<=levOther) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev : this method is not called correctly !"); - // - const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]); - int idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2)); - const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther)); - std::vector offset(ComputeOffsetFromTwoToOne(comAncestor,levOther,thisp,otherp)); - std::vector< std::pair > thispp(thisp->getBLTRRange()),otherpp(MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset)); - // - std::size_t nbOfTurn(levThis-levOther); - for(std::size_t i=0;i > tmp0; - MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(thispp,otherpp,tmp0,false); - otherpp=tmp0; - const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]); - ApplyFactorsOnCompactFrmt(otherpp,curAncestor->getFactors()); - curAncestor=ancestorsOfThis[levThis-1-i]; - int tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i])); - thispp=curAncestor->getPatch(tmpId)->getBLTRRange(); - } - return IsInMyNeighborhood(ghostLev,thispp,otherpp); + return ret; +} + +std::vector MEDCouplingCartesianAMRPatch::computeCellGridSt() const +{ + const MEDCouplingCartesianAMRMeshGen *m(getMesh()); + if(!m) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no mesh held by this !"); + const MEDCouplingCartesianAMRMeshGen *father(m->getFather()); + if(!father) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::computeCellGridSt : no father help by underlying mesh !"); + const std::vector< std::pair >& bltr(getBLTRRange()); + const std::vector& factors(father->getFactors()); + std::vector ret(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(bltr)); + std::transform(ret.begin(),ret.end(),factors.begin(),ret.begin(),std::multiplies()); + return ret; } -bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::vector< std::pair >& p1, const std::vector< std::pair >& p2) +bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(mcIdType ghostLev, const std::vector< std::pair >& p1, const std::vector< std::pair >& p2) { std::size_t thispsize(p1.size()); if(thispsize!=p2.size()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !"); for(std::size_t i=0;i& thispp(p1[i]); - const std::pair& otherpp(p2[i]); + const std::pair& thispp(p1[i]); + const std::pair& otherpp(p2[i]); if(thispp.second > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2) +std::vector< std::vector< std::pair > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2) { if(!p1 || !p2) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev : the input pointers must be not NULL !"); @@ -269,7 +285,7 @@ std::vector< std::vector< std::pair::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++) { - if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev)) + 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 retTmp.push_back(std::pair(*it1,*it2)); } std::vector tmp1((*it1)->getMesh()->getPatches()); @@ -294,7 +310,7 @@ std::vector< std::vector< std::pair >& ret) +void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair >& ret) { if(!p1 || !p2) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf : the input pointers must be not NULL !"); @@ -318,67 +334,126 @@ void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int ghostLev, con * * \saUpdateNeighborsOfOneWithTwoExt */ -void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int ghostLev, const std::vector& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) +void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(mcIdType ghostLev, const std::vector& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) { - const std::vector< std::pair >& p1BLTR(p1->getBLTRRange()); - const std::vector< std::pair >& p2BLTR(p2->getBLTRRange()); + const std::vector< std::pair >& p1BLTR(p1->getBLTRRange()); + const std::vector< std::pair >& p2BLTR(p2->getBLTRRange()); UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2); } -void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghostLev, const std::vector& factors, const std::vector< std::pair >&p1 ,const std::vector< std::pair >&p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) -{//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)] - int dim((int)factors.size()); - std::vector dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2] - std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies());//[12,8] - std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus(),2*ghostLev));//[14,10] - std::vector< std::pair > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)] - std::vector fakeFactors(dim,1); - // - std::vector< std::pair > tmp0,tmp1,tmp2; - MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)] - ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)] - ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)] - std::vector< std::pair > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)] - MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)] - ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)] - MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)] - // - std::vector< std::pair > dimsFine(p2); - ApplyFactorsOnCompactFrmt(dimsFine,factors); - ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev); - // - MEDCouplingAutoRefCountObjectPtr ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2)); - MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1); -} - /*! * Idem than UpdateNeighborsOfOneWithTwo, except that here \a p1 and \a p2 are not sharing the same direct father. * * \sa UpdateNeighborsOfOneWithTwo */ -void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) +void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) { - const std::vector< std::pair >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)] - std::vector< std::pair > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)] - int lev(0); + const std::vector< std::pair >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)] + std::vector< std::pair > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)] + mcIdType lev(0); const MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev)); - std::vector offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4] + std::vector offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4] p2BLTR=MEDCouplingStructuredMesh::TranslateCompactFrmt(p2BLTR,offset);//p2BLTR=[(12,13),(4,9)] UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1BLTR,p2BLTR,dataOnP1,dataOnP2); } -void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) +/*! + * \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 ! + */ +void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2, bool isConservative) { + std::vector< std::pair > p1pp,p2pp; + std::vector factors; + ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,p1,p2,p1pp,p2pp,factors); + // + std::vector dimsP2NotRefined(p2->computeCellGridSt()); + std::vector dimsP2Refined(dimsP2NotRefined); + std::transform(dimsP2NotRefined.begin(),dimsP2NotRefined.end(),factors.begin(),dimsP2Refined.begin(),std::multiplies()); + std::vector< std::pair > p2RefinedAbs(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsP2NotRefined)); + std::vector dimsP2RefinedGhost(dimsP2Refined.size()); + std::transform(dimsP2Refined.begin(),dimsP2Refined.end(),dimsP2RefinedGhost.begin(),std::bind2nd(std::plus(),2*ghostLev)); + MCAuto fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents()); + MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev); + if(isConservative) + { + mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(factors)); + std::transform(fineP2->begin(),fineP2->end(),fineP2->getPointer(),std::bind2nd(std::multiplies(),1./((double)fact))); + } + // + UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1pp,p2pp,dataOnP1,fineP2); +} + +/*! + * \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 ! + * 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 virtually + * on the same level as \a p1. + */ +void MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair >& p1Zone, std::vector< std::pair >& p2Zone, std::vector& factToApplyOn2) +{ + std::vector ancestorsOfThis; + const MEDCouplingCartesianAMRMeshGen *work(p1->getMesh()),*work2(0); + ancestorsOfThis.push_back(work); + while(work) + { + work=work->getFather(); + if(work) + ancestorsOfThis.push_back(work); + } + // + work=p2->getMesh(); + bool found(false); + std::size_t levThis(0),levOther(0); + while(work && !found) + { + work2=work; + work=work->getFather(); + if(work) + { + levOther++; + std::vector::iterator it(std::find(ancestorsOfThis.begin(),ancestorsOfThis.end(),work)); + if(it!=ancestorsOfThis.end()) + { + levThis=std::distance(ancestorsOfThis.begin(),it); + found=true; + } + } + } + if(!found) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : no common ancestor found !"); + if(levThis<=levOther) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev : this method is not called correctly !"); + // + const MEDCouplingCartesianAMRMeshGen *comAncestor(ancestorsOfThis[levThis]); + mcIdType idThis(comAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-1])),idOther(comAncestor->getPatchIdFromChildMesh(work2)); + const MEDCouplingCartesianAMRPatch *thisp(comAncestor->getPatch(idThis)),*otherp(comAncestor->getPatch(idOther)); + std::vector offset(ComputeOffsetFromTwoToOne(comAncestor,ToIdType(levOther),thisp,otherp)); + p1Zone=thisp->getBLTRRange(); p2Zone=MEDCouplingStructuredMesh::TranslateCompactFrmt(otherp->getBLTRRange(),offset); + factToApplyOn2.resize(p1Zone.size()); std::fill(factToApplyOn2.begin(),factToApplyOn2.end(),1); + // + std::size_t nbOfTurn(levThis-levOther); + for(std::size_t i=0;i > tmp0; + MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1Zone,p2Zone,tmp0,false); + p2Zone=tmp0; + const MEDCouplingCartesianAMRMeshGen *curAncestor(ancestorsOfThis[levThis-i]); + ApplyFactorsOnCompactFrmt(p2Zone,curAncestor->getFactors()); + curAncestor=ancestorsOfThis[levThis-1-i]; + const std::vector& factors(curAncestor->getFactors()); + std::transform(factToApplyOn2.begin(),factToApplyOn2.end(),factors.begin(),factToApplyOn2.begin(),std::multiplies()); + mcIdType tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i])); + p1Zone=curAncestor->getPatch(tmpId)->getBLTRRange(); + } } std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const { std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch)); - ret+=_bl_tr.capacity()*sizeof(std::pair); + ret+=_bl_tr.capacity()*sizeof(std::pair); return ret; } -const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, int& lev) +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, mcIdType& lev) { const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh); lev=0; @@ -394,33 +469,33 @@ const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAn return f1; } -std::vector MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, int lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2) +std::vector MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, mcIdType lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2) { if(lev<=0) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : this method is useful only for lev > 0 !"); - int zeLev(lev-1); - int dim(p1->getMesh()->getSpaceDimension()); + mcIdType zeLev(lev-1); + mcIdType dim(p1->getMesh()->getSpaceDimension()); if(p2->getMesh()->getSpaceDimension()!=dim) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : dimension must be the same !"); - std::vector< int > ret(dim,0); - for(int i=0;i ret(dim,0); + for(mcIdType i=0;i_mesh),*f2(p2->_mesh); const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0); - for(int j=0;jgetFather()),*f2tmp(f2->getFather()); - int pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2)); + mcIdType pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2)); p1h=f1tmp->getPatch(pid1); p2h=f2tmp->getPatch(pid2); f1=f1tmp; f2=f2tmp; } - std::vector< std::pair > p2c(p2h->getBLTRRange()); - for(int k=0;k > p2c(p2h->getBLTRRange()); + for(mcIdType k=0;kgetBLTRRange()[k].first; ret[k]*=f1->getFactors()[k]; @@ -429,11 +504,41 @@ std::vector MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const M return ret; } +void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(mcIdType ghostLev, const std::vector& factors, const std::vector< std::pair >&p1 ,const std::vector< std::pair >&p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2) +{//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)] + mcIdType dim(ToIdType(factors.size())); + std::vector dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2] + std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies());//[12,8] + std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus(),2*ghostLev));//[14,10] + std::vector< std::pair > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)] + std::vector fakeFactors(dim,1); + // + std::vector< std::pair > tmp0,tmp1,tmp2; + MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)] + ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)] + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)] + std::vector< std::pair > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)] + MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)] + ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)] + MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)] + // + std::vector< std::pair > dimsFine(p2); + ApplyFactorsOnCompactFrmt(dimsFine,factors); + ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev); + // + MCAuto ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2)); + MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1); +} + +MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(const MEDCouplingCartesianAMRPatch& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father),_bl_tr(other._bl_tr) +{ +} + /*! * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference. * \param [in] factors - the factors per axis. */ -void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair >& partBeforeFact, const std::vector& factors) +void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair >& partBeforeFact, const std::vector& factors) { std::size_t sz(factors.size()); if(sz!=partBeforeFact.size()) @@ -445,29 +550,13 @@ void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::p } } -/*! - * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference. - * \param [in] ghostSize - the ghost size of zone for all axis. - */ -void MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(std::vector< std::pair >& partBeforeFact, int ghostSize) -{ - if(ghostSize<0) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !"); - std::size_t sz(partBeforeFact.size()); - for(std::size_t i=0;i >& partBeforeFact, int ghostSize) +void MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt(std::vector< std::pair >& partBeforeFact, mcIdType ghostSize) { if(ghostSize<0) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !"); @@ -483,31 +572,18 @@ MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartes { } -std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const -{ - return sizeof(MEDCouplingCartesianAMRPatchGF); -} - -MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf) +MEDCouplingCartesianAMRPatchGF *MEDCouplingCartesianAMRPatchGF::deepCopy(MEDCouplingCartesianAMRMeshGen *father) const { - if(!_gf) - throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !"); - _gf->setData(this); + return new MEDCouplingCartesianAMRPatchGF(*this,father); } -void MEDCouplingDataForGodFather::checkGodFatherFrozen() const +std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const { - _tlc.checkConst(); + return sizeof(MEDCouplingCartesianAMRPatchGF); } -bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf) +MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father) { - bool ret(_tlc.keepTrackOfNewTL(gf)); - if(ret) - { - _gf=gf; - } - return ret; } /// @endcond @@ -517,9 +593,9 @@ int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const return _mesh->getSpaceDimension(); } -void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector& newFactors) +void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector& newFactors) { - if(getSpaceDimension()!=(int)newFactors.size()) + if(getSpaceDimension()!=ToIdType(newFactors.size())) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : size of input factors is not equal to the space dimension !"); if(_factors.empty()) { @@ -534,10 +610,10 @@ void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector& newFacto declareAsNew(); } -int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const +mcIdType MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const { - int ret(1); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + mcIdType ret(1); + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1); return ret; } @@ -547,7 +623,7 @@ int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const * The patches in \a this are ignored here. * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap */ -int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const +mcIdType MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const { return _mesh->getNumberOfCells(); } @@ -559,9 +635,9 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const * * \sa getNumberOfCellsAtCurrentLevel */ -int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const +mcIdType MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(mcIdType ghostLev) const { - MEDCouplingAutoRefCountObjectPtr tmp(_mesh->buildWithGhost(ghostLev)); + MCAuto tmp(_mesh->buildWithGhost(ghostLev)); return tmp->getNumberOfCells(); } @@ -569,10 +645,10 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghos * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels * starting from this. The set of cells which size is returned here are generally overlapping each other. */ -int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const +mcIdType MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const { - int ret(_mesh->getNumberOfCells()); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + mcIdType ret=_mesh->getNumberOfCells(); + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { ret+=(*it)->getNumberOfCellsRecursiveWithOverlap(); } @@ -586,10 +662,10 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const * * \sa buildUnstructured */ -int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const +mcIdType MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const { - int ret(_mesh->getNumberOfCells()); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + mcIdType ret=_mesh->getNumberOfCells(); + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { ret-=(*it)->getNumberOfOverlapedCellsForFather(); ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap(); @@ -597,28 +673,57 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() co return ret; } -const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getFather() const +/*! + * This method returns a vector of size equal to getAbsoluteLevelRelativeTo. It allows to find position an absolute position of \a this + * relative to \a ref (that is typically the god father). + * + * \sa getPatchAtPosition + */ +std::vector MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const { - return _father; + if(!ref) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo : input pointer is NULL !"); + std::vector ret; + getPositionRelativeToInternal(ref,ret); + std::reverse(ret.begin(),ret.end()); + return ret; } -const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getGodFather() const +/*! + * \sa getPositionRelativeTo, getMeshAtPosition + */ +const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatchAtPosition(const std::vector& pos) const { - if(_father==0) - return this; - else - return _father->getGodFather(); + std::size_t sz(pos.size()); + if(sz==0) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : empty input -> no patch by definition !"); + mcIdType patchId(pos[0]); + const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId)); + if(sz==1) + return elt; + if(!elt || !elt->getMesh()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !"); + std::vector pos2(pos.begin()+1,pos.end()); + return elt->getMesh()->getPatchAtPosition(pos2); } -/*! - * This method returns the level of \a this. 0 for god father. -1 for children of god father ... - */ -int MEDCouplingCartesianAMRMeshGen::getAbsoluteLevel() const +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getMeshAtPosition(const std::vector& pos) const { - if(_father==0) - return 0; - else - return _father->getAbsoluteLevel()-1; + std::size_t sz(pos.size()); + if(sz==0) + return this; + mcIdType patchId(pos[0]); + const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId)); + if(sz==1) + { + if(!elt) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getMeshAtPosition : NULL patch !"); + return elt->getMesh(); + } + if(!elt || !elt->getMesh()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !"); + std::vector pos2(pos.begin()+1,pos.end()); + return elt->getMesh()->getMeshAtPosition(pos2); } /*! @@ -626,27 +731,11 @@ int MEDCouplingCartesianAMRMeshGen::getAbsoluteLevel() const * * \return std::vector - objects in vector are to be managed (decrRef) by the caller. */ -std::vector MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(int absoluteLev) const +std::vector MEDCouplingCartesianAMRMeshGen::retrieveGridsAt(mcIdType absoluteLev) const { if(absoluteLev<0) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !"); - if(_father) - return getGodFather()->retrieveGridsAt(absoluteLev); - // - std::vector< MEDCouplingAutoRefCountObjectPtr > rets; - retrieveGridsAtInternal(absoluteLev,rets); - std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size()); - for(std::size_t i=0;iretrieveGridsAt(absoluteLev); } /*! @@ -654,13 +743,13 @@ void MEDCouplingCartesianAMRMeshGen::detachFromFather() * a the end cell (\b excluded) of the range for the second element of the pair. * \param [in] factors The factor of refinement per axis (different from 0). */ -void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair >& bottomLeftTopRight, const std::vector& factors) +void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair >& bottomLeftTopRight, const std::vector& factors) { checkFactorsAndIfNotSetAssign(factors); - MEDCouplingAutoRefCountObjectPtr mesh(static_cast(_mesh->buildStructuredSubPart(bottomLeftTopRight))); + MCAuto mesh(static_cast(_mesh->buildStructuredSubPart(bottomLeftTopRight))); mesh->refineWithFactor(factors); - MEDCouplingAutoRefCountObjectPtr zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh)); - MEDCouplingAutoRefCountObjectPtr elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight)); + MCAuto zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh)); + MCAuto elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight)); _patches.push_back(elt); declareAsNew(); } @@ -671,38 +760,38 @@ class InternalPatch : public RefCountObjectOnly { public: InternalPatch():_nb_of_true(0) { } - int getDimension() const { return (int)_part.size(); } + mcIdType getDimension() const { return ToIdType(_part.size()); } double getEfficiency() const { return (double)_nb_of_true/(double)_crit.size(); } - int getNumberOfCells() const { return (int)_crit.size(); } - void setNumberOfTrue(int nboft) { _nb_of_true=nboft; } + mcIdType getNumberOfCells() const { return ToIdType(_crit.size()); } + void setNumberOfTrue(mcIdType nboft) { _nb_of_true=nboft; } std::vector& getCriterion() { return _crit; } const std::vector& getConstCriterion() const { return _crit; } - void setPart(const std::vector< std::pair >& part) { _part=part; } - std::vector< std::pair >& getPart() { return _part; } - const std::vector< std::pair >& getConstPart() const { return _part; } + void setPart(const std::vector< std::pair >& part) { _part=part; } + std::vector< std::pair >& getPart() { return _part; } + const std::vector< std::pair >& getConstPart() const { return _part; } bool presenceOfTrue() const { return _nb_of_true>0; } - std::vector computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); } - std::vector< std::vector > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); } - double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); } - void zipToFitOnCriterion(); + std::vector computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); } + std::vector< std::vector > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); } + double getEfficiencyPerAxis(mcIdType axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); } + void zipToFitOnCriterion(mcIdType minPatchLgth); void updateNumberOfTrue() const; - MEDCouplingAutoRefCountObjectPtr extractPart(const std::vector< std::pair >&partInGlobal) const; - MEDCouplingAutoRefCountObjectPtr deepCpy() const; + MCAuto extractPart(const std::vector< std::pair >&partInGlobal) const; + MCAuto deepCopy() const; protected: ~InternalPatch() { } private: - mutable int _nb_of_true; + mutable mcIdType _nb_of_true; std::vector _crit; //! _part is global - std::vector< std::pair > _part; + std::vector< std::pair > _part; }; -void InternalPatch::zipToFitOnCriterion() +void InternalPatch::zipToFitOnCriterion(mcIdType minPatchLgth) { - std::vector cgs(computeCGS()); + std::vector cgs(computeCGS()); std::vector newCrit; - std::vector< std::pair > newPart,newPart2; - int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart)); + std::vector< std::pair > newPart,newPart2; + mcIdType newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(minPatchLgth,cgs,_crit,newCrit,newPart)); MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2); if(newNbOfTrue!=_nb_of_true) throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !"); @@ -711,14 +800,14 @@ void InternalPatch::zipToFitOnCriterion() void InternalPatch::updateNumberOfTrue() const { - _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true); + _nb_of_true=ToIdType(std::count(_crit.begin(),_crit.end(),true)); } -MEDCouplingAutoRefCountObjectPtr InternalPatch::extractPart(const std::vector< std::pair >&partInGlobal) const +MCAuto InternalPatch::extractPart(const std::vector< std::pair >&partInGlobal) const { - MEDCouplingAutoRefCountObjectPtr ret(new InternalPatch); - std::vector cgs(computeCGS()); - std::vector< std::pair > newPart; + MCAuto ret(new InternalPatch); + std::vector cgs(computeCGS()); + std::vector< std::pair > newPart; MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart); MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(cgs,_crit,newPart,ret->getCriterion()); ret->setPart(partInGlobal); @@ -726,107 +815,110 @@ MEDCouplingAutoRefCountObjectPtr InternalPatch::extractPart(const return ret; } -MEDCouplingAutoRefCountObjectPtr InternalPatch::deepCpy() const +MCAuto InternalPatch::deepCopy() const { - MEDCouplingAutoRefCountObjectPtr ret(new InternalPatch); + MCAuto ret(new InternalPatch); (*ret)=*this; return ret; } -void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace) +void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, mcIdType axisId, mcIdType largestLength, mcIdType& cutPlace) { - cutFound=false; cutPlace=-1; - std::vector ratio(rangeOfAxisId-1); - for(int id=0;id ratio(largestLength-minimumPatchLength,std::numeric_limits::max()); + mcIdType index_min = -1; + double minSemiEfficiencyRatio(std::numeric_limits::max()); + double efficiencyPerAxis[2]; + + for(mcIdType i=minimumPatchLength-1;i > rectH(patchToBeSplit->getConstPart()); + std::vector< std::pair > rectH(patchToBeSplit->getConstPart()); if(h==0) - rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id; + rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+i; else - rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id; - MEDCouplingAutoRefCountObjectPtr p(patchToBeSplit->deepCpy()); - p->zipToFitOnCriterion(); - //anouar rectH ? - efficiency[h]=p->getEfficiencyPerAxis(axisId); + rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+i; + MCAuto p(patchToBeSplit->deepCopy()); + p->zipToFitOnCriterion(bso.getMinimumPatchLength()); + efficiencyPerAxis[h]=p->getEfficiencyPerAxis(axisId); } - ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]); - } - int minCellDirection(bso.getMinCellDirection()),indexMin(-1); - int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1)); - std::vector ratio_inner(dimRatioInner); - double minRatio(1.e10); - for(int i=0; igetConstPart()[axisId].first-1; + + if(index_min==-1) + throw INTERP_KERNEL::Exception("DissectBigPatch : just call to Arthur !"); + + cutPlace=index_min+patchToBeSplit->getConstPart()[axisId].first; } -void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace) +bool FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, mcIdType axisId, mcIdType& cutPlace) { - cutPlace=-1; cutFound=false; - int minCellDirection(bso.getMinCellDirection()); - const int dim(patchToBeSplit->getDimension()); - std::vector< std::vector > signatures(patchToBeSplit->computeSignature()); - for(int id=0;idgetDimension()); + std::vector< std::vector > signatures(patchToBeSplit->computeSignature()); + for(mcIdType id=0;id& signature(signatures[id]); - std::vector hole; + const std::vector& signature(signatures[id]); + std::vector hole; std::vector distance; - int len((int)signature.size()); - for(int i=0;i= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1) - hole.push_back(i); + hole.push_back(i); if(!hole.empty()) { - double center(((double)len/2.)); + mcIdType closestHoleToMiddle(hole[0]); + mcIdType oldDistanceToMiddle(std::abs(hole[0]-len/2)); + mcIdType newDistanceToMiddle(oldDistanceToMiddle); for(std::size_t i=0;igetConstPart()[axisId].first+1; - return ; + { + newDistanceToMiddle=std::abs(hole[i]-len/2); + if(newDistanceToMiddle < oldDistanceToMiddle) + { + oldDistanceToMiddle = newDistanceToMiddle; + closestHoleToMiddle = hole[i]; + } + } + cutPlace=closestHoleToMiddle+patchToBeSplit->getConstPart()[axisId].first; + return true; } } + return false; } -void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId) +bool FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, mcIdType& cutPlace, int& axisId) { - cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true - - const std::vector< std::pair >& part(patchToBeSplit->getConstPart()); - int sign,minCellDirection(bso.getMinCellDirection()); - const int dim(patchToBeSplit->getDimension()); + bool cutFound(false); cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true + const std::vector< std::pair >& part(patchToBeSplit->getConstPart()); + mcIdType sign=0,minimumPatchLength(bso.getMinimumPatchLength()); + const mcIdType dim(patchToBeSplit->getDimension()); - std::vector zeroCrossDims(dim,-1); - std::vector zeroCrossVals(dim,-1); - std::vector< std::vector > signatures(patchToBeSplit->computeSignature()); - for (int id=0;id zeroCrossDims(dim,-1); + std::vector zeroCrossVals(dim,-1); + std::vector< std::vector > signatures(patchToBeSplit->computeSignature()); + for (mcIdType id=0;id& signature(signatures[id]); + const std::vector& signature(signatures[id]); - std::vector derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ; + std::vector derivate_second_order,gradient_absolute,zero_cross,edge,max_cross_list ; std::vector distance ; - for (unsigned int i=1;i= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 ) + if ( i >= (std::size_t)minimumPatchLength-2 && i <= signature.size()-minimumPatchLength-2 ) { - zero_cross.push_back(i) ; + zero_cross.push_back(ToIdType(i)) ; edge.push_back(gradient_absolute[i]) ; } - signe_change.push_back(sign) ; } if ( zero_cross.size() > 0 ) { - int max_cross=*max_element(edge.begin(),edge.end()) ; - for (unsigned int i=0;i(signature.size())/2.0); + for (std::size_t i=0;i(max_cross_list[i])+1-center)); - float distance_min=*min_element(distance.begin(),distance.end()) ; - int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin(); - int best_place = max_cross_list[pos_distance_min] + part[id].first ; + double distance_min=*min_element(distance.begin(),distance.end()) ; + mcIdType pos_distance_min=ToIdType(find(distance.begin(),distance.end(),distance_min)-distance.begin()); + mcIdType best_place = max_cross_list[pos_distance_min] + part[id].first ; if ( max_cross >=0 ) { zeroCrossDims[id] = best_place ; @@ -864,7 +955,6 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna } derivate_second_order.clear() ; gradient_absolute.clear() ; - signe_change.clear() ; zero_cross.clear() ; edge.clear() ; max_cross_list.clear() ; @@ -873,153 +963,182 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna if ( zeroCrossDims[0]!=-1 || zeroCrossDims[1]!=-1 ) { - int max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ; + mcIdType max_cross_dims = *max_element(zeroCrossVals.begin(),zeroCrossVals.end()) ; if (zeroCrossVals[0]==max_cross_dims && zeroCrossVals[1]==max_cross_dims ) { - int nl_left(part[0].second-part[0].first); - int nc_left(part[1].second-part[1].first); + mcIdType nl_left(part[0].second-part[0].first); + mcIdType nc_left(part[1].second-part[1].first); if ( nl_left >= nc_left ) max_cross_dims = 0 ; else max_cross_dims = 1 ; } else - max_cross_dims=std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin(); + max_cross_dims=ToIdType(std::find(zeroCrossVals.begin(),zeroCrossVals.end(),max_cross_dims)-zeroCrossVals.begin()); cutFound=true; cutPlace=zeroCrossDims[max_cross_dims]; - axisId=max_cross_dims ; + axisId=FromIdType(max_cross_dims); } + return cutFound; } -void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace) +bool TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, mcIdType axisId, mcIdType rangeOfAxisId, mcIdType& cutPlace) { - cutFound=false; - if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd()) + if(patchToBeSplit->getEfficiency()<=bso.getEfficiencyGoal()) { - if(rangeOfAxisId>=2*bso.getMinCellDirection()) + if(rangeOfAxisId>=2*bso.getMinimumPatchLength()) { - cutFound=true; cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1; } + else + return false; } else { - if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells()) + if(patchToBeSplit->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || rangeOfAxisId>bso.getMaximumPatchLength()) { - DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace); + DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutPlace); } + else + return false; } + return true; } -MEDCouplingAutoRefCountObjectPtr DealWithNoCut(const InternalPatch *patch) +MCAuto DealWithNoCut(const InternalPatch *patch) { - MEDCouplingAutoRefCountObjectPtr ret(const_cast(patch)); + MCAuto ret(const_cast(patch)); ret->incrRef(); return ret; } -void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector >& listOfPatches) +void DealWithCut(double minPatchLgth, const InternalPatch *patchToBeSplit, int axisId, mcIdType cutPlace, std::vector >& listOfPatches) { - MEDCouplingAutoRefCountObjectPtr leftPart,rightPart; - std::vector< std::pair > rect(patchToBeSplit->getConstPart()); - std::vector< std::pair > leftRect(rect),rightRect(rect); + MCAuto leftPart,rightPart; + std::vector< std::pair > rect(patchToBeSplit->getConstPart()); + std::vector< std::pair > leftRect(rect),rightRect(rect); leftRect[axisId].second=cutPlace+1; rightRect[axisId].first=cutPlace+1; leftPart=patchToBeSplit->extractPart(leftRect); rightPart=patchToBeSplit->extractPart(rightRect); - leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion(); + leftPart->zipToFitOnCriterion(ToIdType(minPatchLgth)); rightPart->zipToFitOnCriterion(ToIdType(minPatchLgth)); listOfPatches.push_back(leftPart); listOfPatches.push_back(rightPart); } /// @endcond +void MEDCouplingCartesianAMRMeshGen::removeAllPatches() +{ + _patches.clear(); + declareAsNew(); +} + +void MEDCouplingCartesianAMRMeshGen::removePatch(mcIdType patchId) +{ + checkPatchId(patchId); + mcIdType sz(ToIdType(_patches.size())),j(0); + std::vector< MCAuto > patches(sz-1); + for(mcIdType i=0;i(_patches[patchId]->getMesh()))->detachFromFather(); + _patches=patches; + declareAsNew(); +} + +mcIdType MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const +{ + return ToIdType(_patches.size()); +} + /*! - * 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. + * This method is a generic algorithm to create patches in \a this (by destroying the patches if any). + * This method uses \a criterion array as a field on cells on this level. + * This method only create patches at level 0 relative to \a this. + * + * This generic algorithm can be degenerated into three child ones, depending on the arguments given; in particular depending + * on whether they are equal to 0 or not. + * 1/ If minimumPatchLength = maximumPatchLength = maximumPatchVolume = 0, then we have the Berger-Rigoutsos algorithm. + * This algorithm was developed in 1991 and seems appropriate for sequential programming. + * 2/ If maximumPatchLength = 0, then we have the Livne algorithm. + * This algorithm was developed in 2004 and is an improvement of the Berger-Rigoutsos algorithm. + * 3/ If maximumPatchVolume = 0, the we have the lmin-lmax algorithm. + * This algorithm was developed by Arthur TALPAERT in 2014 and is an improvement of the Livne algorithm. It is especially + * appropriate for parallel computing, where one patch would be given to one CPU. See Arthur TALPAERT's 2014 CANUM poster + * for more information. + * */ -void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector& criterion, const std::vector& factors) +void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector& criterion, const std::vector& factors) { - int nbCells(getNumberOfCellsAtCurrentLevel()); - if(nbCells!=(int)criterion.size()) - 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 !"); + mcIdType nbCells(getNumberOfCellsAtCurrentLevel()); + if(nbCells!=ToIdType(criterion.size())) + 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 !"); _patches.clear(); - std::vector cgs(_mesh->getCellGridStructure()); - std::vector< MEDCouplingAutoRefCountObjectPtr > listOfPatches,listOfPatchesOK; + std::vector cgs(_mesh->getCellGridStructure()); + std::vector< MCAuto > listOfPatches,listOfPatchesOK; // - MEDCouplingAutoRefCountObjectPtr p(new InternalPatch); - p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart())); + MCAuto p(new InternalPatch); + p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(bso.getMinimumPatchLength(),cgs,criterion,p->getCriterion(),p->getPart())); if(p->presenceOfTrue()) listOfPatches.push_back(p); while(!listOfPatches.empty()) { - std::vector< MEDCouplingAutoRefCountObjectPtr > listOfPatchesTmp; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++) + std::vector< MCAuto > listOfPatchesTmp; + for(std::vector< MCAuto >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++) { // - int axisId,rangeOfAxisId,cutPlace; - bool cutFound; - MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId); - if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()getConstPart(),axisId,largestLength); + if((*it)->getEfficiency()>=bso.getEfficiencyThreshold() && ((*it)->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || largestLength>bso.getMaximumPatchLength())) + { + DissectBigPatch(bso,*it,axisId,largestLength,cutPlace); + DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); + continue; + }//action 1 + if(FindHole(bso,*it,axisId,cutPlace))//axisId overwritten here if FindHole equal to true ! + { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2 + if(FindInflection(bso,*it,cutPlace,axisId))//axisId overwritten here if cutFound equal to true ! + { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3 + if(TryAction4(bso,*it,axisId,largestLength,cutPlace)) + { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4 + else + listOfPatchesOK.push_back(DealWithNoCut(*it)); } listOfPatches=listOfPatchesTmp; } - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++) + for(std::vector< MCAuto >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++) addPatch((*it)->getConstPart(),factors); declareAsNew(); } /*! * 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. + * This method only create patches at level 0 relative to \a this. */ -void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector& factors) +void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector& factors) { if(!criterion || !criterion->isAllocated()) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !"); + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !"); std::vector crit(criterion->toVectorOfBool());//check that criterion has one component. createPatchesFromCriterion(bso,crit,factors); declareAsNew(); } -void MEDCouplingCartesianAMRMeshGen::removeAllPatches() -{ - _patches.clear(); - declareAsNew(); -} - -void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId) -{ - checkPatchId(patchId); - int sz((int)_patches.size()),j(0); - std::vector< MEDCouplingAutoRefCountObjectPtr > patches(sz-1); - for(int i=0;i(_patches[patchId]->getMesh()))->detachFromFather(); - _patches=patches; - declareAsNew(); -} - -int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const +void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayDouble *criterion, const std::vector& factors, double eps) { - return (int)_patches.size(); + if(!criterion) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : null criterion pointer !"); + std::vector inp(criterion->toVectorOfBool(eps)); + createPatchesFromCriterion(bso,inp,factors); } -int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const +mcIdType MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const { - int ret(0); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++) + mcIdType ret(0); + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++) { if((*it)->getMesh()==mesh) return ret; @@ -1036,7 +1155,7 @@ std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGe return ret; } -const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const +const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(mcIdType patchId) const { checkPatchId(patchId); return _patches[patchId]; @@ -1046,10 +1165,10 @@ const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int * This method states if patch2 (with id \a patchId2) is in the neighborhood of patch1 (with id \a patchId1). * The neighborhood size is defined by \a ghostLev in the reference of \a this ( \b not in the reference of patches !). */ -bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const +bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(mcIdType patchId1, mcIdType patchId2, mcIdType ghostLev) const { const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2)); - return p1->isInMyNeighborhood(p2,GetGhostLevelInFineRef(ghostLev,_factors)); + return p1->isInMyNeighborhood(p2,ghostLev); } /*! @@ -1065,13 +1184,13 @@ bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int p * \throw if \a cellFieldOnThis is NULL or not allocated * \sa fillCellFieldOnPatch, MEDCouplingIMesh::SpreadCoarseToFine */ -DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const +DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(mcIdType patchId, const DataArrayDouble *cellFieldOnThis) const { if(!cellFieldOnThis || !cellFieldOnThis->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !"); const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId)); const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh()); - MEDCouplingAutoRefCountObjectPtr ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents()); + MCAuto ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents()); ret->copyStringInfoFrom(*cellFieldOnThis); MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors()); return ret.retn(); @@ -1087,12 +1206,17 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patc * * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, bool isConservative) const { if(!cellFieldOnThis || !cellFieldOnThis->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !"); const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId)); MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors()); + if(isConservative) + { + mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies(),1./((double)fact))); + } } /*! @@ -1106,12 +1230,17 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const Dat * * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, mcIdType ghostLev, bool isConservative) const { if(!cellFieldOnThis || !cellFieldOnThis->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !"); const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId)); MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev); + if(isConservative) + { + mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies(),1./((double)fact))); + } } /*! @@ -1123,7 +1252,7 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, cons * \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. * \param [in] ghostLev - The size of the ghost zone (must be >=0 !) */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, mcIdType ghostLev) const { if(!cellFieldOnThis || !cellFieldOnThis->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !"); @@ -1137,23 +1266,22 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int pat * * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on. * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId. - * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled. * \param [in] ghostLev - The size of the ghost zone (must be >=0 !) * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const. * * \sa fillCellFieldOnPatchOnlyGhostAdv */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector& arrsOnPatches) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(mcIdType patchId, const DataArrayDouble *cellFieldOnThis, mcIdType ghostLev, const std::vector& arrsOnPatches, bool isConservative) const { - int nbp(getNumberOfPatches()); - if(nbp!=(int)arrsOnPatches.size()) + mcIdType nbp(getNumberOfPatches()); + if(nbp!=ToIdType(arrsOnPatches.size())) { std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } DataArrayDouble *theFieldToFill(const_cast(arrsOnPatches[patchId])); // first, do as usual - fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev); + fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev,isConservative); fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches); } @@ -1163,25 +1291,25 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, c * * \sa getPatchIdsInTheNeighborhoodOf */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector& arrsOnPatches) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(mcIdType patchId, mcIdType ghostLev, const std::vector& arrsOnPatches) const { - int nbp(getNumberOfPatches()); - if(nbp!=(int)arrsOnPatches.size()) + mcIdType nbp(getNumberOfPatches()); + if(nbp!=ToIdType(arrsOnPatches.size())) { std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId)); DataArrayDouble *theFieldToFill(const_cast(arrsOnPatches[patchId])); - std::vector ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev)); - for(std::vector::const_iterator it=ids.begin();it!=ids.end();it++) + std::vector ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev)); + for(std::vector::const_iterator it=ids.begin();it!=ids.end();it++) { const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it)); MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]); } } -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(mcIdType ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const { MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor); } @@ -1192,17 +1320,23 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on. * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId. * \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. + * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied. * * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() ) * \throw if \a cellFieldOnPatch is NULL or not allocated * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(mcIdType patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, bool isConservative) const { if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !"); const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId)); MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis); + if(!isConservative) + { + mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis); + } } /*! @@ -1213,17 +1347,23 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, c * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId. * \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. * \param [in] ghostLev The size of ghost zone (must be >= 0 !) + * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied. * * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() ) * \throw if \a cellFieldOnPatch is NULL or not allocated * \sa fillCellFieldComingFromPatch */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(mcIdType patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, mcIdType ghostLev, bool isConservative) const { if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !"); const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId)); MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev); + if(!isConservative) + { + mcIdType fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis); + } } /*! @@ -1232,13 +1372,13 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patch * * \param [in] patchId - the id of the considered patch. * \param [in] ghostLev - the size of the neighborhood. - * \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. + * \return DataArrayIdType * - 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. */ -DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const +DataArrayIdType *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(mcIdType patchId, mcIdType ghostLev) const { - int nbp(getNumberOfPatches()); - MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(0,1); - for(int i=0;i ret(DataArrayIdType::New()); ret->alloc(0,1); + for(mcIdType i=0;i part(_mesh->buildUnstructured()); + MCAuto part(_mesh->buildUnstructured()); std::vector bs(_mesh->getNumberOfCells(),false); - std::vector cgs(_mesh->getCellGridStructure()); - std::vector< MEDCouplingAutoRefCountObjectPtr > msSafe(_patches.size()+1); + std::vector cgs(_mesh->getCellGridStructure()); + std::vector< MCAuto > msSafe(_patches.size()+1); std::size_t ii(0); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++) + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++) { MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs); msSafe[ii+1]=(*it)->getMesh()->buildUnstructured(); } - MEDCouplingAutoRefCountObjectPtr eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs)); + MCAuto eltsOff(DataArrayIdType::BuildListOfSwitchedOff(bs)); msSafe[0]=static_cast(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false)); std::vector< const MEDCouplingUMesh * > ms(msSafe.size()); for(std::size_t i=0;i cells; - std::vector< MEDCouplingAutoRefCountObjectPtr > cellsSafe; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + std::vector< MCAuto > cellsSafe; + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { const MEDCouplingCartesianAMRPatch *patch(*it); if(patch) { - MEDCouplingAutoRefCountObjectPtr cell(patch->getMesh()->getImageMesh()->asSingleCell()); - MEDCouplingAutoRefCountObjectPtr cell1SGT(cell->build1SGTUnstructured()); + MCAuto cell(patch->getMesh()->getImageMesh()->asSingleCell()); + MCAuto cell1SGT(cell->build1SGTUnstructured()); cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT); } } @@ -1293,13 +1433,13 @@ MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop( MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const { std::vector patches; - std::vector< MEDCouplingAutoRefCountObjectPtr > patchesSafe; - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + std::vector< MCAuto > patchesSafe; + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { const MEDCouplingCartesianAMRPatch *patch(*it); if(patch) { - MEDCouplingAutoRefCountObjectPtr patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured()); + MCAuto patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured()); patchesSafe.push_back(patchMesh); patches.push_back(patchMesh); } } @@ -1311,30 +1451,30 @@ MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenO * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with. * \sa buildUnstructured */ -MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector& recurseArrs) const +MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(mcIdType ghostSz, const std::vector& recurseArrs) const { if(recurseArrs.empty()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !"); // std::vector bs(_mesh->getNumberOfCells(),false); - std::vector cgs(_mesh->getCellGridStructure()); - std::vector< MEDCouplingAutoRefCountObjectPtr > msSafe(_patches.size()+1); + std::vector cgs(_mesh->getCellGridStructure()); + std::vector< MCAuto > msSafe(_patches.size()+1); std::size_t ii(0); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++) + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++) { MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs); std::vector tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs)); msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs); } - MEDCouplingAutoRefCountObjectPtr eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs)); + MCAuto eltsOff(DataArrayIdType::BuildListOfSwitchedOff(bs)); // - MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingFieldDouble::New(ON_CELLS)); - MEDCouplingAutoRefCountObjectPtr arr2(extractGhostFrom(ghostSz,recurseArrs[0])); + MCAuto ret(MEDCouplingFieldDouble::New(ON_CELLS)); + MCAuto arr2(extractGhostFrom(ghostSz,recurseArrs[0])); arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end()); ret->setArray(arr2); ret->setName(arr2->getName()); - MEDCouplingAutoRefCountObjectPtr part(_mesh->buildUnstructured()); - MEDCouplingAutoRefCountObjectPtr mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false)); + MCAuto part(_mesh->buildUnstructured()); + MCAuto mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false)); ret->setMesh(mesh); msSafe[0]=ret; // @@ -1349,13 +1489,13 @@ MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseW * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part. * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz). */ -DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const +DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(mcIdType ghostSz, const DataArrayDouble *arr) const { - std::vector st(_mesh->getCellGridStructure()); - std::vector< std::pair > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st)); - std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus(),2*ghostSz)); - MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(p,ghostSz); - MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p)); + std::vector st(_mesh->getCellGridStructure()); + std::vector< std::pair > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st)); + std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus(),2*ghostSz)); + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz); + MCAuto ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p)); return ret.retn(); } @@ -1364,12 +1504,12 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, c * * \sa fillCellFieldOnPatchOnlyGhostAdv */ -std::vector MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(int patchId, int ghostLev) const +std::vector MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(mcIdType patchId, mcIdType ghostLev) const { - std::vector ret; - int nbp(getNumberOfPatches()); + std::vector ret; + mcIdType nbp(getNumberOfPatches()); // - for(int i=0;i MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf( return ret; } -MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop, - const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0) +/*! + * This method returns a dump python of \a this. It is useful for users of createPatchesFromCriterion method for debugging. + * + * \sa dumpPatchesOf, createPatchesFromCriterion, createPatchesFromCriterionML + */ +std::string MEDCouplingCartesianAMRMeshGen::buildPythonDumpOfThis() const +{ + std::ostringstream oss; + oss << "amr=MEDCouplingCartesianAMRMesh(\""<< getImageMesh()->getName() << "\"," << getSpaceDimension() << ",["; + std::vector ngs(getImageMesh()->getNodeGridStructure()); + std::vector orig(getImageMesh()->getOrigin()),dxyz(getImageMesh()->getDXYZ()); + std::copy(ngs.begin(),ngs.end(),std::ostream_iterator(oss,",")); + oss << "],["; + std::copy(orig.begin(),orig.end(),std::ostream_iterator(oss,",")); + oss << "],["; + std::copy(dxyz.begin(),dxyz.end(),std::ostream_iterator(oss,",")); + oss << "])\n"; + dumpPatchesOf("amr",oss); + return oss.str(); +} + +MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const MEDCouplingCartesianAMRMeshGen& other):RefCountObject(other),_mesh(other._mesh),_patches(other._patches),_factors(other._factors) +{ + const MEDCouplingIMesh *mesh(other._mesh); + if(mesh) + _mesh=static_cast(mesh->deepCopy()); + std::size_t sz(other._patches.size()); + for(std::size_t i=0;ideepCopy(this); + } +} + +MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const mcIdType *nodeStrctStart, const mcIdType *nodeStrctStop, + const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop) { _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop); } -MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):_father(father) +MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) { - if(!_father) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : empty father !"); if(!mesh) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !"); - mesh->checkCoherency(); + mesh->checkConsistencyLight(); _mesh=mesh; _mesh->incrRef(); } -void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const +void MEDCouplingCartesianAMRMeshGen::checkPatchId(mcIdType patchId) const { - int sz(getNumberOfPatches()); + mcIdType sz(getNumberOfPatches()); if(patchId<0 || patchId>=sz) { std::ostringstream oss; oss << "MEDCouplingCartesianAMRMeshGen::checkPatchId : invalid patchId (" << patchId << ") ! Must be in [0," << sz << ") !"; @@ -1404,9 +1577,9 @@ void MEDCouplingCartesianAMRMeshGen::checkPatchId(int patchId) const } } -void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector& factors) +void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::vector& factors) { - if(getSpaceDimension()!=(int)factors.size()) + if(getSpaceDimension()!=ToIdType(factors.size())) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign : invalid size of factors ! size must be equal to the spaceDimension !"); if(_factors.empty()) { @@ -1419,29 +1592,29 @@ void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::ve } } -void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr >& grids) const +void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(mcIdType lev, std::vector< MCAuto >& grids) const { if(lev==0) { const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast(this));//tony - MEDCouplingAutoRefCountObjectPtr elt(new MEDCouplingCartesianAMRPatchGF(const_cast(thisc))); + MCAuto elt(new MEDCouplingCartesianAMRPatchGF(const_cast(thisc))); grids.push_back(DynamicCastSafe(elt)); } else if(lev==1) { - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { const MEDCouplingCartesianAMRPatch *pt(*it); if(pt) { - MEDCouplingAutoRefCountObjectPtr tmp1(*it); + MCAuto tmp1(*it); grids.push_back(DynamicCastSafe(tmp1)); } } } else { - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { const MEDCouplingCartesianAMRPatch *pt(*it); if(pt) @@ -1450,13 +1623,13 @@ void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vecto } } -int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const std::vector& factors) +mcIdType MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(mcIdType ghostLev, const std::vector& factors) { if(ghostLev<0) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !"); if(factors.empty()) throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !"); - int ghostLevInPatchRef; + mcIdType ghostLevInPatchRef; if(ghostLev==0) ghostLevInPatchRef=0; else @@ -1474,11 +1647,11 @@ int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const s */ std::vector MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector& all) const { - int maxLev(getMaxNumberOfLevelsRelativeToThis()); + mcIdType maxLev(getMaxNumberOfLevelsRelativeToThis()); std::vector ret; std::vector meshes(1,this); std::size_t kk(0); - for(int i=0;i meshesTmp; for(std::vector::const_iterator it=meshes.begin();it!=meshes.end();it++) @@ -1500,21 +1673,44 @@ std::vector MEDCouplingCartesianAMRMeshGen::extractSubT return ret; } +void MEDCouplingCartesianAMRMeshGen::dumpPatchesOf(const std::string& varName, std::ostream& oss) const +{ + std::size_t j(0); + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) + { + const MEDCouplingCartesianAMRPatch *patch(*it); + if(patch) + { + std::ostringstream oss2; oss2 << varName << ".addPatch(["; + const std::vector< std::pair >& bltr(patch->getBLTRRange()); + std::size_t sz(bltr.size()); + for(std::size_t i=0;i(oss2,",")); + oss2 << "])\n"; + oss << oss2.str(); + std::ostringstream oss3; oss3 << varName << "[" << j++ << "]"; + patch->getMesh()->dumpPatchesOf(oss3.str(),oss); + } + } +} + std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const { return sizeof(MEDCouplingCartesianAMRMeshGen); } -std::vector MEDCouplingCartesianAMRMeshGen::getDirectChildren() const +std::vector MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull() const { std::vector ret; - if((const MEDCouplingIMesh *)_mesh) - ret.push_back((const MEDCouplingIMesh *)_mesh); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) - { - if((const MEDCouplingCartesianAMRPatch*)*it) - ret.push_back((const MEDCouplingCartesianAMRPatch*)*it); - } + ret.push_back((const MEDCouplingIMesh *)_mesh); + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) + ret.push_back((const MEDCouplingCartesianAMRPatch*)*it); return ret; } @@ -1522,7 +1718,7 @@ void MEDCouplingCartesianAMRMeshGen::updateTime() const { if((const MEDCouplingIMesh *)_mesh) updateTimeWith(*_mesh); - for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++) + for(std::vector< MCAuto >::const_iterator it=_patches.begin();it!=_patches.end();it++) { const MEDCouplingCartesianAMRPatch *elt(*it); if(!elt) @@ -1533,64 +1729,250 @@ void MEDCouplingCartesianAMRMeshGen::updateTime() const } } -MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(father,mesh) +MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh),_father(father) { + if(!_father) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh) constructor : empty father !"); } -MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop, +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getFather() const +{ + return _father; +} + +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getGodFather() const +{ + if(!_father) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getGodFather : Impossible to find a god father because there is a hole in chain !"); + return _father->getGodFather(); +} + +/*! + * This method returns the level of \a this. 0 for god father. 1 for children of god father ... + */ +mcIdType MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel() const +{ + if(!_father) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel : Impossible to find a god father because there is a hole in chain !"); + return _father->getAbsoluteLevel()+1; +} + +void MEDCouplingCartesianAMRMeshSub::detachFromFather() +{ + _father=0; + declareAsNew(); +} + +std::vector< std::pair > MEDCouplingCartesianAMRMeshSub::positionRelativeToGodFather(std::vector& st) const +{ + st=_father->getFactors(); + std::size_t dim(st.size()); + std::vector prev(st); + mcIdType id(_father->getPatchIdFromChildMesh(this)); + const MEDCouplingCartesianAMRPatch *p(_father->getPatch(id)); + std::vector< std::pair > ret(p->getBLTRRange()); + std::vector delta(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(ret)),start(dim); + std::transform(delta.begin(),delta.end(),prev.begin(),delta.begin(),std::multiplies()); + for(std::size_t i=0;i()); + const MEDCouplingCartesianAMRMeshGen *it(_father); + while(!dynamic_cast(it)) + { + const MEDCouplingCartesianAMRMeshSub *itc(static_cast(it)); + mcIdType id2(itc->_father->getPatchIdFromChildMesh(itc)); + const MEDCouplingCartesianAMRPatch *p2(itc->_father->getPatch(id2)); + const std::vector< std::pair >& start2(p2->getBLTRRange()); + std::vector tmp(dim); + for(std::size_t i=0;i_father->getFactors(); + std::transform(st.begin(),st.end(),prev.begin(),st.begin(),std::multiplies()); + std::transform(st.begin(),st.end(),tmp.begin(),tmp.begin(),std::multiplies()); + std::transform(start.begin(),start.end(),tmp.begin(),start.begin(),std::plus()); + it=itc->_father; + } + for(std::size_t i=0;igetAbsoluteLevelRelativeTo(ref)+1; +} + +MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(const MEDCouplingCartesianAMRMeshSub& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRMeshGen(other),_father(father) +{ +} + +MEDCouplingCartesianAMRMeshSub *MEDCouplingCartesianAMRMeshSub::deepCopy(MEDCouplingCartesianAMRMeshGen *fath) const +{ + return new MEDCouplingCartesianAMRMeshSub(*this,fath); +} + +/*! + * \sa getPositionRelativeTo + */ +void MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector& ret) const +{ + if(this==ref) + return ; + if(!_father) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal : ref is not in the progeny of this !"); + mcIdType myId(_father->getPatchIdFromChildMesh(this)); + ret.push_back(myId); + _father->getPositionRelativeToInternal(ref,ret); +} + +MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const mcIdType *nodeStrctStart, const mcIdType *nodeStrctStop, const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop) { return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop); } -void MEDCouplingCartesianAMRMesh::setData(MEDCouplingDataForGodFather *data) +MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(MEDCouplingIMesh *mesh) { - MEDCouplingDataForGodFather *myData(_data); - if(myData==data) + return new MEDCouplingCartesianAMRMesh(mesh); +} + +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getFather() const +{ + //I'm god father ! No father ! + return 0; +} + +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getGodFather() const +{ + return this; +} + +mcIdType MEDCouplingCartesianAMRMesh::getAbsoluteLevel() const +{ + return 0; +} + +void MEDCouplingCartesianAMRMesh::detachFromFather() +{//not a bug - do nothing +} + +std::vector< std::pair > MEDCouplingCartesianAMRMesh::positionRelativeToGodFather(std::vector& st) const +{ + st=_mesh->getCellGridStructure(); + return MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st); +} + +mcIdType MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const +{ + if(this==ref) + return 0; + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !"); +} + +std::vector MEDCouplingCartesianAMRMesh::retrieveGridsAt(mcIdType absoluteLev) const +{ + std::vector< MCAuto > rets; + retrieveGridsAtInternal(absoluteLev,rets); + std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size()); + for(std::size_t i=0;i& bso, const DataArrayDouble *criterion, const std::vector< std::vector >& factors, double eps) +{ + std::size_t nbOfLevs(bso.size()); + if(nbOfLevs!=factors.size()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : size of vectors must be the same !"); + if(nbOfLevs==0) return ; - if(myData) - myData->changeGodFather(0); - _data=data; - if(data) - data->incrRef(); + if(!bso[0]) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : pointers in 1st arg must be not NULL !"); + createPatchesFromCriterion(*bso[0],criterion,factors[0],eps); + for(std::size_t i=1;i elts(retrieveGridsAt(ToIdType((i)))); + std::size_t sz(elts.size()); + std::vector< MCAuto > elts2(sz); + std::vector< MCAuto > elts3(sz); + for(std::size_t ii=0;ii > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1; + MCAuto att(MEDCouplingAMRAttribute::New(this,fieldNames,0)); + att->alloc(); + DataArrayDouble *tmpDa(const_cast(att->getFieldOn(this,TMP_STR))); + tmpDa->deepCopyFrom(*criterion); + att->synchronizeCoarseToFine(); + for(std::size_t ii=0;iigetFieldOn(const_cast(elts[ii]->getMesh()),TMP_STR)); + elts3[ii]=const_cast(critOnLeaf); elts3[ii]->incrRef(); + } + att=0; + for(std::size_t ii=0;ii(elts[ii]->getMesh())->createPatchesFromCriterion(*bso[i],elts3[ii],factors[i],eps); + } } -void MEDCouplingCartesianAMRMesh::allocData() const +void MEDCouplingCartesianAMRMesh::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector& ret) const { - checkData(); - _data->alloc(); + } -void MEDCouplingCartesianAMRMesh::deallocData() const +MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const MEDCouplingCartesianAMRMesh& other):MEDCouplingCartesianAMRMeshGen(other) { - checkData(); - _data->dealloc(); } -MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop, +MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const mcIdType *nodeStrctStart, const mcIdType *nodeStrctStop, const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop) { } -std::vector MEDCouplingCartesianAMRMesh::getDirectChildren() const +MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh) { - std::vector ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren()); - const MEDCouplingDataForGodFather *pt(_data); - if(pt) - ret.push_back(pt); - return ret; } -void MEDCouplingCartesianAMRMesh::checkData() const +std::vector MEDCouplingCartesianAMRMesh::getDirectChildrenWithNull() const { - const MEDCouplingDataForGodFather *data(_data); - if(!data) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkData : no data set !"); + std::vector ret(MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull()); + return ret; } MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh() { - MEDCouplingDataForGodFather *data(_data); - if(data) - data->changeGodFather(0); }