From: geay Date: Mon, 26 May 2014 12:49:48 +0000 (+0200) Subject: Coarse to fine using neighborhood for AMR. X-Git-Tag: V7_5_0a1~37^2~34 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=546b56abffb99edb377559e3e0803130ff538baa;p=modules%2Fmed.git Coarse to fine using neighborhood for AMR. --- diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx index fd2fde384..b923249b6 100644 --- a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx +++ b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx @@ -72,6 +72,45 @@ int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr); } +/*! + * 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. + * + * \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. + */ +bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const +{ + if(ghostLev<0) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the size of the neighborhood must be >= 0 !"); + if(!other) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !"); + const std::vector< std::pair >& thisp(getBLTRRange()); + const std::vector< std::pair >& otherp(other->getBLTRRange()); + std::size_t thispsize(thisp.size()); + if(thispsize!=otherp.size()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !"); + for(std::size_t i=0;i& thispp(thisp[i]); + const std::pair& otherpp(otherp[i]); + if(thispp.second=0 !"); + const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2)); + if(_factors.empty()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::isPatchInNeighborhoodOf : no factors defined !"); + int ghostLevInPatchRef; + if(ghostLev==0) + ghostLevInPatchRef=0; + else + { + ghostLevInPatchRef=(ghostLev-1)/_factors[0]+1; + for(std::size_t i=0;i<_factors.size();i++) + ghostLevInPatchRef=std::max(ghostLevInPatchRef,_factors[i]/ghostLev+1); + } + return p1->isInMyNeighborhood(p2,ghostLevInPatchRef); +} + /*! * This method creates a new cell field array on given \a patchId patch in \a this starting from a coarse cell field on \a this \a cellFieldOnThis. * This method can be seen as a fast projection from the cell field \a cellFieldOnThis on \c this->getImageMesh() to a refined part of \a this @@ -565,7 +627,8 @@ DataArrayDouble *MEDCouplingCartesianAMRMesh::createCellFieldOnPatch(int patchId } /*! - * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of + * This method is equivalent to MEDCouplingCartesianAMRMesh::createCellFieldOnPatch except that here instead of creating a new instance + * it fills the value into the \a cellFieldOnPatch data. * * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on. * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId. @@ -581,6 +644,64 @@ void MEDCouplingCartesianAMRMesh::fillCellFieldOnPatch(int patchId, const DataAr MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors()); } +/*! + * This method is the generalization of fillCellFieldOnPatch method. This method only projects coarse to fine without considering the + * potential neighbor patches covered by the ghost cells of patch with id \a patchId. + * + * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on. + * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId. + * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled. + * \param [in] ghostLev - The size of the ghost zone (must be >=0 !) + * + * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv + */ +void MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) 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); +} + +/*! + * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called. + * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately. + * + * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on. + * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId. + * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled. + * \param [in] ghostLev - The size of the ghost zone (must be >=0 !) + * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const. + */ +void MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector& arrsOnPatches) const +{ + int nbp(getNumberOfPatches()); + if(nbp!=(int)arrsOnPatches.size()) + { + std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + // first, do as usual + fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,const_cast(arrsOnPatches[patchId]),ghostLev); + // + const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId)); + const std::vector< std::pair >& refBLTR(refP->getBLTRRange()); + for(int i=0;i >& otherBLTR(otherP->getBLTRRange()); + std::vector< std::pair > tmp0; + MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(refBLTR,otherBLTR,tmp0); + ApplyFactorsOnCompactFrmt(tmp0,_factors); + ApplyGhostOnCompactFrmt(tmp0,ghostLev); + //std::vector dims(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); + } + } +} + /*! * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId. * @@ -590,7 +711,7 @@ void MEDCouplingCartesianAMRMesh::fillCellFieldOnPatch(int patchId, const DataAr * * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() ) * \throw if \a cellFieldOnPatch is NULL or not allocated - * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse + * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost */ void MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const { @@ -600,6 +721,48 @@ void MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch(int patchId, cons MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis); } +/*! + * This method is the extension of MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch managing the ghost cells. If this + * method is called with \a ghostLev equal to 0 it behaves exactly as MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch. + * + * \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] ghostLev The size of ghost zone (must be >= 0 !) + * + * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() ) + * \throw if \a cellFieldOnPatch is NULL or not allocated + * \sa fillCellFieldComingFromPatch + */ +void MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) 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); +} + +/*! + * This method finds all patches (located by their ids) that are in the neighborhood of patch with id \a patchId. The neighborhood size is + * defined by ghostLev. + * + * \param [in] patchId - the id of the considered patch. + * \param [in] ghostLev - the size of the neighborhood. + * \return DataArrayInt * - the newly allocated array containing the list of patches in the neighborhood of the considered patch. This array is to be deallocated by the caller. + */ +DataArrayInt *MEDCouplingCartesianAMRMesh::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const +{ + int nbp(getNumberOfPatches()); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(0,1); + for(int i=0;ipushBackSilent(i); + } + return ret.retn(); +} + MEDCouplingUMesh *MEDCouplingCartesianAMRMesh::buildUnstructured() const { MEDCouplingAutoRefCountObjectPtr part(_mesh->buildUnstructured()); @@ -684,6 +847,38 @@ void MEDCouplingCartesianAMRMesh::checkFactorsAndIfNotSetAssign(const 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 MEDCouplingCartesianAMRMesh::ApplyFactorsOnCompactFrmt(std::vector< std::pair >& partBeforeFact, const std::vector& factors) +{ + std::size_t sz(factors.size()); + if(sz!=partBeforeFact.size()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::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("MEDCouplingCartesianAMRMesh::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !"); + std::size_t sz(partBeforeFact.size()); + for(std::size_t i=0;i >& bottomLeftTopRight, const std::vector& factors); // end of direct forward to _mesh MEDCOUPLING_EXPORT int getNumberOfOverlapedCellsForFather() const; + MEDCOUPLING_EXPORT bool isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const; // basic set/get MEDCOUPLING_EXPORT const std::vector< std::pair >& getBLTRRange() const { return _bl_tr; } MEDCOUPLING_EXPORT const MEDCouplingCartesianAMRMesh *getMesh() const { return _mesh; } @@ -92,9 +94,14 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void removePatch(int patchId); MEDCOUPLING_EXPORT int getNumberOfPatches() const; MEDCOUPLING_EXPORT const MEDCouplingCartesianAMRPatch *getPatch(int patchId) const; + MEDCOUPLING_EXPORT bool isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const; MEDCOUPLING_EXPORT DataArrayDouble *createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const; MEDCOUPLING_EXPORT void fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const; + MEDCOUPLING_EXPORT void fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const; + MEDCOUPLING_EXPORT void fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector& arrsOnPatches) const; MEDCOUPLING_EXPORT void fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const; + MEDCOUPLING_EXPORT void fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) const; + MEDCOUPLING_EXPORT DataArrayInt *findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const; // MEDCOUPLING_EXPORT MEDCouplingUMesh *buildUnstructured() const; MEDCOUPLING_EXPORT MEDCoupling1SGTUMesh *buildMeshFromPatchEnvelop() const; @@ -104,6 +111,8 @@ namespace ParaMEDMEM MEDCouplingCartesianAMRMesh(MEDCouplingCartesianAMRMesh *father, MEDCouplingIMesh *mesh); void checkPatchId(int patchId) const; void checkFactorsAndIfNotSetAssign(const std::vector& factors); + static void ApplyFactorsOnCompactFrmt(std::vector< std::pair >& partBeforeFact, const std::vector& factors); + static void ApplyGhostOnCompactFrmt(std::vector< std::pair >& partBeforeFact, int ghostSize); protected: MEDCOUPLING_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; MEDCOUPLING_EXPORT std::vector getDirectChildren() const; diff --git a/src/MEDCoupling/MEDCouplingIMesh.cxx b/src/MEDCoupling/MEDCouplingIMesh.cxx index 30458429b..969e36489 100644 --- a/src/MEDCoupling/MEDCouplingIMesh.cxx +++ b/src/MEDCoupling/MEDCouplingIMesh.cxx @@ -278,6 +278,8 @@ MEDCouplingIMesh *MEDCouplingIMesh::asSingleCell() const */ void MEDCouplingIMesh::CondenseFineToCoarse(const std::vector& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, DataArrayDouble *coarseDA) { + if(coarseSt.size()!=fineLocInCoarse.size() || coarseSt.size()!=facts.size()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : All input vectors (dimension) must have the same size !"); if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the parameters 1 or 3 are NULL or not allocated !"); int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseSt)),nbOfTuplesInFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(fineLocInCoarse)); @@ -397,12 +399,12 @@ void MEDCouplingIMesh::CondenseFineToCoarse(const std::vector& coarseSt, co void MEDCouplingIMesh::CondenseFineToCoarseGhost(const std::vector& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, DataArrayDouble *coarseDA, int ghostSize) { if(ghostSize<0) - throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : ghost level >= 0 !"); + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : ghost level has to be >= 0 !"); + if(coarseSt.size()!=fineLocInCoarse.size() || coarseSt.size()!=facts.size()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : All input vectors (dimension) must have the same size !"); if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : the parameters 1 or 3 are NULL or not allocated !"); std::vector coarseStG(coarseSt.size()); std::transform(coarseSt.begin(),coarseSt.end(),coarseStG.begin(),std::bind2nd(std::plus(),2*ghostSize)); - //std::vector fineStG(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); - //std::transform(fineStG.begin(),fineStG.end(),fineStG.begin(),std::bind2nd(std::plus(),2*ghostSize)); int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseStG)); int nbCompo(fineDA->getNumberOfComponents()); if(coarseDA->getNumberOfComponents()!=nbCompo) @@ -411,16 +413,20 @@ void MEDCouplingIMesh::CondenseFineToCoarseGhost(const std::vector& coarseS throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarseGhost : the size of fineLocInCoarse (4th param) and facts (5th param) must be equal to the sier of coarseSt (2nd param) !"); if(coarseDA->getNumberOfTuples()!=nbOfTuplesInCoarseExp) { - std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarseGhost : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !"; + std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarseGhost : Expecting " << nbOfTuplesInCoarseExp << " tuples in coarse DataArray having " << coarseDA->getNumberOfTuples() << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - //int nbTuplesFine(fineDA->getNumberOfTuples()); - //int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies())); - /*if(nbTuplesFine!=fact*nbOfTuplesInFineExp) + // + std::vector fineStG(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); + std::transform(fineStG.begin(),fineStG.end(),facts.begin(),fineStG.begin(),std::multiplies()); + std::transform(fineStG.begin(),fineStG.end(),fineStG.begin(),std::bind2nd(std::plus(),2*ghostSize)); + int nbTuplesFine(fineDA->getNumberOfTuples()),nbTuplesFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(fineStG)); + if(fineDA->getNumberOfTuples()!=nbTuplesFineExp) { - std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarseGhost : Invalid number of tuples (" << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!"; + std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarseGhost : Expecting " << nbTuplesFineExp << " tuples in fine DataArray having " << nbTuplesFine << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); - }*/ + } + // double *outPtr(coarseDA->getPointer()); const double *inPtr(fineDA->begin()); // @@ -488,6 +494,8 @@ void MEDCouplingIMesh::CondenseFineToCoarseGhost(const std::vector& coarseS */ void MEDCouplingIMesh::SpreadCoarseToFine(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts) { + if(coarseSt.size()!=fineLocInCoarse.size() || coarseSt.size()!=facts.size()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : All input vectors (dimension) must have the same size !"); if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the parameters 1 or 3 are NULL or not allocated !"); int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseSt)),nbOfTuplesInFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(fineLocInCoarse)); @@ -589,11 +597,12 @@ void MEDCouplingIMesh::SpreadCoarseToFine(const DataArrayDouble *coarseDA, const void MEDCouplingIMesh::SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, int ghostSize) { if(ghostSize<0) - throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : ghost level >= 0 !"); + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : ghost level has to be >= 0 !"); + if(coarseSt.size()!=fineLocInCoarse.size() || coarseSt.size()!=facts.size()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : All input vectors (dimension) must have the same size !"); if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated()) throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : the parameters 1 or 3 are NULL or not allocated !"); std::vector coarseStG(coarseSt.size()); std::transform(coarseSt.begin(),coarseSt.end(),coarseStG.begin(),std::bind2nd(std::plus(),2*ghostSize)); - //std::vector fineStG(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); std::transform(fineStG.begin(),fineStG.end(),fineStG.begin(),std::bind2nd(std::plus(),2*ghostSize)); int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseStG)); int nbCompo(fineDA->getNumberOfComponents()); if(coarseDA->getNumberOfComponents()!=nbCompo) @@ -605,15 +614,16 @@ void MEDCouplingIMesh::SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFineGhost : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - /*int nbTuplesFine(fineDA->getNumberOfTuples()); - if(nbTuplesFine%nbOfTuplesInFineExp!=0) - throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhost : Invalid nb of tuples in fine DataArray regarding its structure !"); - int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies())); - if(nbTuplesFine!=fact*nbOfTuplesInFineExp) + // + std::vector fineStG(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); + std::transform(fineStG.begin(),fineStG.end(),facts.begin(),fineStG.begin(),std::multiplies()); + std::transform(fineStG.begin(),fineStG.end(),fineStG.begin(),std::bind2nd(std::plus(),2*ghostSize)); + int nbTuplesFine(fineDA->getNumberOfTuples()),nbTuplesFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(fineStG)); + if(fineDA->getNumberOfTuples()!=nbTuplesFineExp) { - std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFineGhost : Invalid number of tuples (" << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!"; + std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFineGhost : Expecting " << nbTuplesFineExp << " tuples in fine DataArray having " << nbTuplesFine << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); - }*/ + } // double *outPtr(fineDA->getPointer()); const double *inPtr(coarseDA->begin()); diff --git a/src/MEDCoupling/MEDCouplingStructuredMesh.cxx b/src/MEDCoupling/MEDCouplingStructuredMesh.cxx index 19e7690e3..8d5126f9b 100644 --- a/src/MEDCoupling/MEDCouplingStructuredMesh.cxx +++ b/src/MEDCoupling/MEDCouplingStructuredMesh.cxx @@ -1343,7 +1343,7 @@ void MEDCouplingStructuredMesh::SwitchOnIdsFrom(const std::vector& st, cons * \param [in] partCompactFormat The compact subpart to be enabled. * \param [out] fieldOut the result of the extraction. * - * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom, SwitchOnIdsFrom + * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom, SwitchOnIdsFrom, ExtractFieldOfDoubleFrom */ void MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(const std::vector& st, const std::vector& fieldOfBool, const std::vector< std::pair >& partCompactFormat, std::vector& fieldOut) { @@ -1392,13 +1392,76 @@ void MEDCouplingStructuredMesh::ExtractFieldOfBoolFrom(const std::vector& s } } +/*! + * This method is close to SwitchOnIdsFrom except that here, a sub field \a fieldOut is built starting from the input field \a fieldOfDbl having the structure \a st. + * The extraction is defined by \a partCompactFormat. + * + * \param [in] st The entity structure. + * \param [in] fieldOfDbl field of doubles having a number of tuples equal to \c MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(st). + * \param [in] partCompactFormat The compact subpart to be enabled. + * \return DataArrayDouble * -the result of the extraction. + * + * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom, SwitchOnIdsFrom, ExtractFieldOfBoolFrom + */ +DataArrayDouble *MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(const std::vector& st, const DataArrayDouble *fieldOfDbl, const std::vector< std::pair >& partCompactFormat) +{ + if(!fieldOfDbl || !fieldOfDbl->isAllocated()) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : input array of double is NULL or not allocated!"); + if(st.size()!=partCompactFormat.size()) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : input arrays must have the same size !"); + if(fieldOfDbl->getNumberOfTuples()!=DeduceNumberOfGivenStructure(st)) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom : invalid size of input array of double regarding the structure !"); + std::vector dims(GetDimensionsFromCompactFrmt(partCompactFormat)); + int nbOfTuplesOfOutField(DeduceNumberOfGivenStructure(dims)),nbComp(fieldOfDbl->getNumberOfComponents()); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayDouble::New()); ret->alloc(nbOfTuplesOfOutField,nbComp); + ret->copyStringInfoFrom(*fieldOfDbl); + double *ptRet(ret->getPointer()); + const double *fieldOfDblPtr(fieldOfDbl->begin()); + switch(st.size()) + { + case 3: + { + for(int i=0;i >& bigInAbs, const std::vector< std::pair >& partOfBigInAbs, std::vector< std::pair >& partOfBigRelativeToBig) { @@ -1466,7 +1529,7 @@ void MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(const std:: * If the range contains invalid values regarding sructure an exception will be thrown. * * \return DataArrayInt * - a new object. - * \sa MEDCouplingStructuredMesh::IsPartStructured, MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt, SwitchOnIdsFrom, ExtractFieldOfBoolFrom + * \sa MEDCouplingStructuredMesh::IsPartStructured, MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt, SwitchOnIdsFrom, ExtractFieldOfBoolFrom, ExtractFieldOfDoubleFrom */ DataArrayInt *MEDCouplingStructuredMesh::BuildExplicitIdsFrom(const std::vector& st, const std::vector< std::pair >& partCompactFormat) { diff --git a/src/MEDCoupling/MEDCouplingStructuredMesh.hxx b/src/MEDCoupling/MEDCouplingStructuredMesh.hxx index 2cde046e1..dc5b78590 100644 --- a/src/MEDCoupling/MEDCouplingStructuredMesh.hxx +++ b/src/MEDCoupling/MEDCouplingStructuredMesh.hxx @@ -75,6 +75,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT static std::vector GetDimensionsFromCompactFrmt(const std::vector< std::pair >& partCompactFormat); MEDCOUPLING_EXPORT static void SwitchOnIdsFrom(const std::vector& st, const std::vector< std::pair >& partCompactFormat, std::vector& vectToSwitchOn); MEDCOUPLING_EXPORT static void ExtractFieldOfBoolFrom(const std::vector& st, const std::vector& fieldOfBool, const std::vector< std::pair >& partCompactFormat, std::vector& fieldOut); + MEDCOUPLING_EXPORT static DataArrayDouble *ExtractFieldOfDoubleFrom(const std::vector& st, const DataArrayDouble *fieldOfDbl, const std::vector< std::pair >& partCompactFormat); MEDCOUPLING_EXPORT static void ChangeReferenceFromGlobalOfCompactFrmt(const std::vector< std::pair >& bigInAbs, const std::vector< std::pair >& partOfBigInAbs, std::vector< std::pair >& partOfBigRelativeToBig); MEDCOUPLING_EXPORT static void ChangeReferenceToGlobalOfCompactFrmt(const std::vector< std::pair >& bigInAbs, const std::vector< std::pair >& partOfBigRelativeToBig, std::vector< std::pair >& partOfBigInAbs); MEDCOUPLING_EXPORT static DataArrayInt *BuildExplicitIdsFrom(const std::vector& st, const std::vector< std::pair >& partCompactFormat); diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index a6bc608f4..548c998e5 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -300,6 +300,7 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::MEDCouplingStructuredMesh::build1SGTUnstructured; %newobject ParaMEDMEM::MEDCouplingStructuredMesh::build1SGTSubLevelMesh; %newobject ParaMEDMEM::MEDCouplingStructuredMesh::BuildExplicitIdsFrom; +%newobject ParaMEDMEM::MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom; %newobject ParaMEDMEM::MEDCouplingStructuredMesh::Build1GTNodalConnectivity; %newobject ParaMEDMEM::MEDCouplingStructuredMesh::Build1GTNodalConnectivityOfSubLevelMesh; %newobject ParaMEDMEM::MEDCouplingCMesh::New; @@ -325,6 +326,7 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getFather; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getPatch; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::createCellFieldOnPatch; +%newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::findPatchesInTheNeighborhoodOf; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::__getitem__; %newobject ParaMEDMEM::DenseMatrix::New; %newobject ParaMEDMEM::DenseMatrix::deepCpy; @@ -2868,6 +2870,13 @@ namespace ParaMEDMEM return MEDCouplingStructuredMesh::BuildExplicitIdsFrom(tmp5,inp); } + static DataArrayDouble *ExtractFieldOfDoubleFrom(const std::vector& st, const DataArrayDouble *fieldOfDbl, PyObject *partCompactFormat) throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > inp; + convertPyToVectorPairInt(partCompactFormat,inp); + return MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,fieldOfDbl,inp); + } + static int DeduceNumberOfGivenRangeInCompactFrmt(PyObject *part) throw(INTERP_KERNEL::Exception) { std::vector< std::pair > inp; @@ -4703,6 +4712,7 @@ namespace ParaMEDMEM int getNumberOfCellsRecursiveWithoutOverlap() const throw(INTERP_KERNEL::Exception); int getMaxNumberOfLevelsRelativeToThis() const throw(INTERP_KERNEL::Exception); int getNumberOfOverlapedCellsForFather() const throw(INTERP_KERNEL::Exception); + bool isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const throw(INTERP_KERNEL::Exception); %extend { PyObject *getBLTRRange() const throw(INTERP_KERNEL::Exception) @@ -4773,6 +4783,7 @@ namespace ParaMEDMEM int getNumberOfCellsAtCurrentLevel() const throw(INTERP_KERNEL::Exception); int getNumberOfCellsRecursiveWithOverlap() const throw(INTERP_KERNEL::Exception); int getNumberOfCellsRecursiveWithoutOverlap() const throw(INTERP_KERNEL::Exception); + bool isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const throw(INTERP_KERNEL::Exception); // int getNumberOfPatches() const throw(INTERP_KERNEL::Exception); MEDCouplingUMesh *buildUnstructured() const throw(INTERP_KERNEL::Exception); @@ -4783,7 +4794,10 @@ namespace ParaMEDMEM void createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector& factors) throw(INTERP_KERNEL::Exception); DataArrayDouble *createCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis) const throw(INTERP_KERNEL::Exception); void fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const throw(INTERP_KERNEL::Exception); + void fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const throw(INTERP_KERNEL::Exception); void fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const throw(INTERP_KERNEL::Exception); + void fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) const throw(INTERP_KERNEL::Exception); + DataArrayInt *findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const throw(INTERP_KERNEL::Exception); %extend { static MEDCouplingCartesianAMRMesh *New(const std::string& meshName, int spaceDim, PyObject *nodeStrct, PyObject *origin, PyObject *dxyz) throw(INTERP_KERNEL::Exception)