X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingCartesianAMRMesh.cxx;h=cf8a37b37d0cde69a591a2681cc3b730d1f383b8;hb=943d5f6fa12e585a425212a5fc6bd657a535a7b4;hp=34fb21fec5fcd3dce4d72e6e6c3180873356248b;hpb=aab3c03f8ed731235533bc24eb444837f6f8bd30;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx index 34fb21fec..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 @@ -55,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); @@ -71,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; } @@ -91,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); @@ -123,7 +134,7 @@ 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 } /*! @@ -161,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. @@ -178,7 +189,44 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCa std::vector< std::pair > thispp,otherpp; std::vector factors; ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,this,other,thispp,otherpp,factors); - return IsInMyNeighborhood(ghostLev,thispp,otherpp); + 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 @@ -237,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()); @@ -312,7 +360,7 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, /*! * \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) +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; @@ -326,6 +374,11 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghost 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); } @@ -463,7 +516,7 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghost 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)] + 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)] @@ -477,6 +530,10 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghost 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. @@ -493,22 +550,6 @@ 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;iincrRef(); -} - -void MEDCouplingDataForGodFather::checkGodFatherFrozen() const +std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const { - _tlc.checkConst(); + return sizeof(MEDCouplingCartesianAMRPatchGF); } -bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf) +MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father) { - bool ret(_tlc.keepTrackOfNewTL(gf)); - if(ret) - { - _gf=gf; - if(gf) - gf->incrRef(); - } - return ret; } /// @endcond @@ -647,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); } /*! @@ -680,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); } /*! @@ -734,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; @@ -747,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 !"); @@ -783,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); @@ -865,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 ) { @@ -903,7 +944,7 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna for (unsigned int i=0;i=0 ) @@ -914,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() ; @@ -940,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) @@ -969,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()); @@ -978,28 +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()) @@ -1008,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; } @@ -1038,7 +1120,7 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER 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(); @@ -1052,81 +1134,6 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER createPatchesFromCriterion(bso,inp,factors); } -/*! - * This method creates a multi level patches split at once. - * This method calls as times as size of \a bso createPatchesFromCriterion. Size of \a bso and size of \a factors must be the same ! - * - * \param [in] bso - * \param [in] criterion - * \param [in] factors - * \param [in] eps - See DataArrayDouble::toVectorOfBool for more information about the semantic of eps. - * - * \sa createPatchesFromCriterion - */ -void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterionML(const std::vector& 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("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterionML : size of vectors must be the same !"); - if(nbOfLevs==0) - return ; - if(!bso[0]) - throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::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)(nbOfLevs-1))); - 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 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(); -} - int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const { int ret(0); @@ -1160,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); } /*! @@ -1198,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))); + } } /*! @@ -1217,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))); + } } /*! @@ -1254,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()) @@ -1264,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); } @@ -1303,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(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); + } } /*! @@ -1324,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); + } } /*! @@ -1465,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)); - MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(p,ghostSz); + MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz); MEDCouplingAutoRefCountObjectPtr ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p)); return ret.retn(); } @@ -1489,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(); @@ -1611,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; } @@ -1644,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, @@ -1654,14 +1840,136 @@ MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop); } +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 +{ + 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(!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::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector& ret) const +{ + +} + +MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const MEDCouplingCartesianAMRMesh& other):MEDCouplingCartesianAMRMeshGen(other) +{ +} + MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *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 MEDCouplingCartesianAMRMesh::getDirectChildrenWithNull() const { - std::vector ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren()); + std::vector ret(MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull()); return ret; }