X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingCartesianAMRMesh.cxx;h=cf8a37b37d0cde69a591a2681cc3b730d1f383b8;hb=943d5f6fa12e585a425212a5fc6bd657a535a7b4;hp=9a71e5a92c69e5d141751902e693404cd5ace5d6;hpb=5c36866f7cf797b79f705a7c06882f1ad87062c7;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx index 9a71e5a92..cf8a37b37 100644 --- 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-2015 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" @@ -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->deepCpy(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; } @@ -90,6 +97,11 @@ MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianA throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !"); } +MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRPatch::deepCpy(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); @@ -122,12 +134,13 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesian 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); + return IsInMyNeighborhood(ghostLev==0?0:1,thisp,otherp);//make hypothesis that nb this->_mesh->getFather->getFactors() is >= ghostLev } /*! * 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. + * the must be >= 0. This method works even if \a this and \a other does not share the same father. But the level between their common + * ancestor must be the same. If they don't have the same ancestor an exception will be thrown. * * \param [in] other - The other patch * \param [in] ghostLev - The size of the neighborhood zone. @@ -137,7 +150,7 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesian * \throw if \a this and \a other have not the same space dimension. * \throw if there is not common ancestor of \a this and \a other. * - * \sa isInMyNeighborhood + * \sa isInMyNeighborhood, isInMyNeighborhoodDiffLev */ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const { @@ -152,13 +165,83 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartes std::vector offset(ComputeOffsetFromTwoToOne(com,lev,this,other)); const std::vector< std::pair >& thisp(getBLTRRange()); std::vector< std::pair > otherp(other->getBLTRRange()); - std::size_t sz(offset.size()); - for(std::size_t i=0;i= 0. This method works even if \a this and \a other does not share the same father. + * \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. + * + * \throw if \a this or \a other are invalid (end before start). + * \throw if \a ghostLev is \b not >= 0 . + * \throw if \a this and \a other have not the same space dimension. + * \throw if there is not common ancestor of \a this and \a other. + * + * \sa isInMyNeighborhoodExt + */ +bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const +{ + 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(); + while(fath) + { + int 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;iigetFather(); + } + 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) @@ -185,6 +268,184 @@ bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::v return true; } +/*! + * \sa FindNeighborsOfSubPatchesOf + */ +std::vector< std::vector< std::pair > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2) +{ + if(!p1 || !p2) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev : the input pointers must be not NULL !"); + std::vector< std::vector< std::pair > > ret; + std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()),p2Work(p2->getMesh()->getPatches()); + while(!p1Work.empty()) + { + std::vector< std::pair > retTmp; + std::vector p1Work2,p2Work2; + for(std::vector::const_iterator it1=p1Work.begin();it1!=p1Work.end();it1++) + { + for(std::vector::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++) + { + 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()); + p1Work2.insert(p1Work2.end(),tmp1.begin(),tmp1.end()); + } + for(std::vector::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++) + { + std::vector tmp2((*it2)->getMesh()->getPatches()); + p2Work2.insert(p2Work2.end(),tmp2.begin(),tmp2.end()); + } + ret.push_back(retTmp); + p1Work=p1Work2; + p2Work=p2Work2; + } + return ret; +} + +/*! + * This method returns all pair of patches (pa,pb) so that pb is in the neighborhood of pa (size of neighborhood is \a ghostLev). + * pa is a refinement (a child) of \b p1 and pb is equal to \a p2. So the returned pair do not have the same level as it is the case for + * FindNeighborsOfSubPatchesOfSameLev. + * + * \sa FindNeighborsOfSubPatchesOfSameLev + */ +void MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int 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 !"); + std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()); + while(!p1Work.empty()) + { + std::vector p1Work2; + for(std::vector::const_iterator it0=p1Work.begin();it0!=p1Work.end();it0++) + { + if((*it0)->isInMyNeighborhoodDiffLev(p2,ghostLev)) + ret.push_back(std::pair(*it0,p2)); + std::vector tmp2((*it0)->getMesh()->getPatches()); + p1Work2.insert(p1Work2.end(),tmp2.begin(),tmp2.end()); + } + p1Work=p1Work2; + } +} + +/*! + * \a p1 and \a p2 are expected to be neighbors (inside the \a ghostLev zone). This method updates \a dataOnP1 only in the ghost part using a part of \a dataOnP2. + * + * \saUpdateNeighborsOfOneWithTwoExt + */ +void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int 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()); + UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2); +} + +/*! + * 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) +{ + 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 MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev)); + 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); +} + +/*! + * \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(int 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)); + MEDCouplingAutoRefCountObjectPtr fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents()); + MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev); + if(isConservative) + { + int 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 virtualy + * on the same level as \a p1. + */ +void MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev(int 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]); + 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)); + 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()); + int tmpId(curAncestor->getPatchIdFromChildMesh(ancestorsOfThis[levThis-2-i])); + p1Zone=curAncestor->getPatch(tmpId)->getBLTRRange(); + } +} + std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const { std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch)); @@ -212,12 +473,12 @@ std::vector MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const M { 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()); 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_mesh),*f2(p2->_mesh); const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0); @@ -243,35 +504,86 @@ std::vector MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const M return ret; } -MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh) +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)] + 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); + // + MEDCouplingAutoRefCountObjectPtr 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) { } -std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const +/*! + * \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) { - return sizeof(MEDCouplingCartesianAMRPatchGF); + std::size_t sz(factors.size()); + if(sz!=partBeforeFact.size()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !"); + for(std::size_t i=0;i >& partBeforeFact, int ghostSize) +{ + if(ghostSize<0) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !"); + std::size_t sz(partBeforeFact.size()); + for(std::size_t i=0;isetData(this); } -void MEDCouplingDataForGodFather::checkGodFatherFrozen() const +MEDCouplingCartesianAMRPatchGF *MEDCouplingCartesianAMRPatchGF::deepCpy(MEDCouplingCartesianAMRMeshGen *father) const { - _tlc.checkConst(); + return new MEDCouplingCartesianAMRPatchGF(*this,father); } -bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf) +std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const +{ + return sizeof(MEDCouplingCartesianAMRPatchGF); +} + +MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father) { - bool ret(_tlc.keepTrackOfNewTL(gf)); - if(ret) - { - _gf=gf; - } - return ret; } /// @endcond @@ -361,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 !"); + int 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; + int 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); } /*! @@ -394,23 +735,7 @@ std::vector MEDCouplingCartesianAMRMeshGen::r { 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); } /*! @@ -448,7 +773,7 @@ public: 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(); + void zipToFitOnCriterion(int minPatchLgth); void updateNumberOfTrue() const; MEDCouplingAutoRefCountObjectPtr extractPart(const std::vector< std::pair >&partInGlobal) const; MEDCouplingAutoRefCountObjectPtr deepCpy() const; @@ -461,12 +786,12 @@ private: std::vector< std::pair > _part; }; -void InternalPatch::zipToFitOnCriterion() +void InternalPatch::zipToFitOnCriterion(int minPatchLgth) { std::vector cgs(computeCGS()); std::vector newCrit; std::vector< std::pair > newPart,newPart2; - int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart)); + int 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 !"); @@ -497,46 +822,45 @@ MEDCouplingAutoRefCountObjectPtr InternalPatch::deepCpy() const 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, int axisId, int largestLength, int& cutPlace) { - cutFound=false; cutPlace=-1; - std::vector ratio(rangeOfAxisId-1); - for(int id=0;id ratio(largestLength-minimumPatchLength,std::numeric_limits::max()); + int index_min = -1; + double minSemiEfficiencyRatio(std::numeric_limits::max()); + double efficiencyPerAxis[2]; + + for(int i=minimumPatchLength-1;i > 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; + rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+i; MEDCouplingAutoRefCountObjectPtr p(patchToBeSplit->deepCpy()); - p->zipToFitOnCriterion(); - //anouar rectH ? - efficiency[h]=p->getEfficiencyPerAxis(axisId); + 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, int axisId, int& cutPlace) { - cutPlace=-1; cutFound=false; - int minCellDirection(bso.getMinCellDirection()); + cutPlace=-1; + int minimumPatchLength(bso.getMinimumPatchLength()); const int dim(patchToBeSplit->getDimension()); std::vector< std::vector > signatures(patchToBeSplit->computeSignature()); for(int id=0;id 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.)); + int closestHoleToMiddle(hole[0]); + int oldDistanceToMiddle(std::abs(hole[0]-len/2)); + int 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, int& cutPlace, int& axisId) { - cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true - + 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()); - int sign,minCellDirection(bso.getMinCellDirection()); + int sign,minimumPatchLength(bso.getMinimumPatchLength()); const int dim(patchToBeSplit->getDimension()); std::vector zeroCrossDims(dim,-1); @@ -579,18 +907,18 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna { 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) ; edge.push_back(gradient_absolute[i]) ; } - signe_change.push_back(sign) ; } if ( zero_cross.size() > 0 ) { @@ -617,7 +944,7 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna for (unsigned int i=0;i=0 ) @@ -628,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() ; @@ -654,26 +980,30 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna cutPlace=zeroCrossDims[max_cross_dims]; axisId=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, int axisId, int rangeOfAxisId, int& 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) @@ -683,7 +1013,7 @@ MEDCouplingAutoRefCountObjectPtr DealWithNoCut(const InternalPatc return ret; } -void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector >& listOfPatches) +void DealWithCut(double minPatchLgth, const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector >& listOfPatches) { MEDCouplingAutoRefCountObjectPtr leftPart,rightPart; std::vector< std::pair > rect(patchToBeSplit->getConstPart()); @@ -692,27 +1022,65 @@ void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, rightRect[axisId].first=cutPlace+1; leftPart=patchToBeSplit->extractPart(leftRect); rightPart=patchToBeSplit->extractPart(rightRect); - leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion(); + leftPart->zipToFitOnCriterion(minPatchLgth); rightPart->zipToFitOnCriterion(minPatchLgth); listOfPatches.push_back(leftPart); listOfPatches.push_back(rightPart); } /// @endcond +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 +{ + return (int)_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) { 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 !"); + 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; // MEDCouplingAutoRefCountObjectPtr p(new InternalPatch); - p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart())); + p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(bso.getMinimumPatchLength(),cgs,criterion,p->getCriterion(),p->getPart())); if(p->presenceOfTrue()) listOfPatches.push_back(p); while(!listOfPatches.empty()) @@ -721,21 +1089,22 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER for(std::vector< MEDCouplingAutoRefCountObjectPtr >::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; } @@ -746,38 +1115,23 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER /*! * 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) { 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 @@ -813,7 +1167,7 @@ const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const { const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2)); - return p1->isInMyNeighborhood(p2,GetGhostLevelInFineRef(ghostLev,_factors)); + return p1->isInMyNeighborhood(p2,ghostLev); } /*! @@ -851,12 +1205,17 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patc * * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int 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) + { + int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies(),1./((double)fact))); + } } /*! @@ -870,12 +1229,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(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int 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) + { + int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies(),1./((double)fact))); + } } /*! @@ -907,7 +1271,7 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int pat * * \sa fillCellFieldOnPatchOnlyGhostAdv */ -void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector& arrsOnPatches) const +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector& arrsOnPatches, bool isConservative) const { int nbp(getNumberOfPatches()); if(nbp!=(int)arrsOnPatches.size()) @@ -917,7 +1281,7 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, c } 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); } @@ -929,60 +1293,50 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, c */ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector& arrsOnPatches) const { - int nbp(getNumberOfPatches()),dim(getSpaceDimension()); + int nbp(getNumberOfPatches()); if(nbp!=(int)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()); } - DataArrayDouble *theFieldToFill(const_cast(arrsOnPatches[patchId])); const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId)); - const std::vector< std::pair >& refBLTR(refP->getBLTRRange());//[(1,4),(2,4)] - std::vector dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(refBLTR));//[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),ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev)); - // + DataArrayDouble *theFieldToFill(const_cast(arrsOnPatches[patchId])); + std::vector ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev)); for(std::vector::const_iterator it=ids.begin();it!=ids.end();it++) { const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it)); - const std::vector< std::pair >& otherBLTR(otherP->getBLTRRange());//[(4,5),(3,4)] - std::vector< std::pair > tmp0,tmp1,tmp2; - MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(refBLTR,otherBLTR,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(otherBLTR,refBLTR,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(otherBLTR); - ApplyFactorsOnCompactFrmt(dimsFine,_factors); - ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev); - // - MEDCouplingAutoRefCountObjectPtr ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),arrsOnPatches[*it],tmp2)); - MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,theFieldToFill); + 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 +{ + MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor); +} + /*! * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId. * * \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(int 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) + { + int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis); + } } /*! @@ -993,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(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int 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) + { + int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors())); + MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis); + } } /*! @@ -1134,7 +1494,7 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, c 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)); - ApplyGhostOnCompactFrmt(p,ghostSz); + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz); MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p)); return ret.retn(); } @@ -1158,16 +1518,49 @@ std::vector MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf( return ret; } +/*! + * 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->deepCpy()); + std::size_t sz(other._patches.size()); + for(std::size_t i=0;ideepCpy(this); + } +} + 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) + 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(); @@ -1230,56 +1623,6 @@ void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vecto } } -/*! - * \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 MEDCouplingCartesianAMRMeshGen::ApplyFactorsOnCompactFrmt(std::vector< std::pair >& partBeforeFact, const std::vector& factors) -{ - std::size_t sz(factors.size()); - if(sz!=partBeforeFact.size()) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !"); - for(std::size_t i=0;i >& partBeforeFact, int ghostSize) -{ - if(ghostSize<0) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !"); - std::size_t sz(partBeforeFact.size()); - for(std::size_t i=0;i >& partBeforeFact, int ghostSize) -{ - if(ghostSize<0) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !"); - std::size_t sz(partBeforeFact.size()); - for(std::size_t i=0;i& factors) { if(ghostLev<0) @@ -1330,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< MEDCouplingAutoRefCountObjectPtr >::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); + 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 MEDCouplingCartesianAMRPatch*)*it); return ret; } @@ -1363,8 +1729,109 @@ 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 !"); +} + +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 ... + */ +int 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); + int 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)); + int 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::deepCpy(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 !"); + int myId(_father->getPatchIdFromChildMesh(this)); + ret.push_back(myId); + _father->getPositionRelativeToInternal(ref,ret); } MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop, @@ -1373,28 +1840,122 @@ MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop); } -void MEDCouplingCartesianAMRMesh::setData(MEDCouplingDataForGodFather *data) +MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(MEDCouplingIMesh *mesh) +{ + return new MEDCouplingCartesianAMRMesh(mesh); +} + +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getFather() const +{ + //I'm god father ! No father ! + return 0; +} + +const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getGodFather() const +{ + return this; +} + +int MEDCouplingCartesianAMRMesh::getAbsoluteLevel() const { - MEDCouplingDataForGodFather *myData(_data); - if(myData==data) + 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); +} + +int 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(int absoluteLev) const +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > 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((int)(i))); + std::size_t sz(elts.size()); + std::vector< MEDCouplingAutoRefCountObjectPtr > elts2(sz); + std::vector< MEDCouplingAutoRefCountObjectPtr > elts3(sz); + for(std::size_t ii=0;ii > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1; + MEDCouplingAutoRefCountObjectPtr att(MEDCouplingAMRAttribute::New(this,fieldNames,0)); + att->alloc(); + DataArrayDouble *tmpDa(const_cast(att->getFieldOn(this,TMP_STR))); + tmpDa->cpyFrom(*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(int ghostLev) const +void MEDCouplingCartesianAMRMesh::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector& ret) const { - checkData(); - _data->alloc(ghostLev); + } -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, @@ -1402,25 +1963,16 @@ MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& mesh { } -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); }