X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDCoupling%2FMEDCouplingCartesianAMRMesh.cxx;h=cf8a37b37d0cde69a591a2681cc3b730d1f383b8;hb=943d5f6fa12e585a425212a5fc6bd657a535a7b4;hp=9ae34266a7c0f77f8491c038c581099288ccea53;hpb=ee1d91dd1a7a0f9da39125e0be67ff4bbf1d95f4;p=tools%2Fmedcoupling.git diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx index 9ae34266a..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 @@ -78,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; } @@ -135,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 } /*! @@ -193,6 +192,43 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCa 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()); @@ -324,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; @@ -338,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); } @@ -732,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; @@ -745,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 !"); @@ -781,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); @@ -863,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 ) { @@ -901,7 +944,7 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna for (unsigned int i=0;i=0 ) @@ -912,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() ; @@ -938,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) @@ -967,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()); @@ -976,7 +1022,7 @@ 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); } @@ -1008,8 +1054,21 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const } /*! - * 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) { @@ -1021,7 +1080,7 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER 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()) @@ -1030,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; } @@ -1645,16 +1705,12 @@ std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() c 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; } @@ -1707,6 +1763,44 @@ void MEDCouplingCartesianAMRMeshSub::detachFromFather() 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;i > MEDCouplingCartesianAMRMesh::positionRelativeToGodFather(std::vector& st) const +{ + st=_mesh->getCellGridStructure(); + return MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st); +} + int MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const { if(this==ref) @@ -1858,9 +1963,13 @@ MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& mesh { } -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; }