From: geay Date: Mon, 2 Jun 2014 16:22:41 +0000 (+0200) Subject: Attributes for AMR cartesian mesh developped. Ready to test. X-Git-Tag: V7_5_0a1~2^2~32^2~25 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=daa2c5dc8a6e6a83230545296fac630603904644;p=tools%2Fmedcoupling.git Attributes for AMR cartesian mesh developped. Ready to test. --- diff --git a/src/MEDCoupling/MEDCouplingAMRAttribute.cxx b/src/MEDCoupling/MEDCouplingAMRAttribute.cxx index ca83e5be3..433620760 100644 --- a/src/MEDCoupling/MEDCouplingAMRAttribute.cxx +++ b/src/MEDCoupling/MEDCouplingAMRAttribute.cxx @@ -21,6 +21,8 @@ #include "MEDCouplingAMRAttribute.hxx" #include "MEDCouplingMemArray.hxx" +#include + using namespace ParaMEDMEM; DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair >& fieldNames) @@ -54,6 +56,104 @@ void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::ve } } +std::vector DataArrayDoubleCollection::retrieveFields() const +{ + std::size_t sz(_arrs.size()); + std::vector ret(sz); + for(std::size_t i=0;i(tmp); + if(ret[i]) + ret[i]->incrRef(); + } + return ret; +} + +DataArrayDouble *DataArrayDoubleCollection::retrieveFieldWithName(const std::string& name) const +{ + std::vector vec; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_arrs.begin();it!=_arrs.end();it++) + { + const DataArrayDouble *obj(*it); + if(obj) + { + if(obj->getName()==name) + { + DataArrayDouble *ret(const_cast(obj)); + if(ret) + ret->incrRef(); + return ret; + } + else + { + vec.push_back(obj->getName()); + } + } + } + std::ostringstream oss; oss << "DataArrayDoubleCollection::retrieveFieldWithName : fieldName \"" << name << "\" does not exist in this ! Possibilities are :"; + std::copy(vec.begin(),vec.end(),std::ostream_iterator(oss," ")); + throw INTERP_KERNEL::Exception(oss.str().c_str()); +} + +void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse) +{ + if(!fine || !coarse) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collections must be non NULL !"); + std::size_t sz(coarse->_arrs.size()); + if(fine->_arrs.size()!=sz) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !"); + for(std::size_t i=0;ifillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i],coarse->_arrs[i],ghostLev); +} + +void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine) +{ + if(!fine || !coarse) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collections must be non NULL !"); + std::size_t sz(coarse->_arrs.size()); + if(fine->_arrs.size()!=sz) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !"); + for(std::size_t i=0;ifillCellFieldOnPatchGhost(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev); +} + +void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector& children, const std::vector& fieldsOnFine) +{ + if(!fatherOfFineMesh) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : father is NULL !"); + std::size_t sz(children.size()); + if(fieldsOnFine.size()!=sz) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : sizes of vectors mismatch !"); + if(sz<=1) + return ; + std::size_t nbOfCall(fieldsOnFine[0]->_arrs.size()); + for(std::size_t i=0;igetPatchIdFromChildMesh(children[i])!=(int)i) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : internal error !"); + for(std::size_t i=1;i_arrs.size()) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineEachOther : the collection of DataArrayDouble must have all the same size !"); + for(std::size_t i=0;i arrs(sz); + for(std::size_t j=0;j_arrs[i]; + fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs); + } +} + +void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine) +{ + if(!fine || !coarse) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collections must be non NULL !"); + std::size_t sz(coarse->_arrs.size()); + if(fine->_arrs.size()!=sz) + throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !"); + for(std::size_t i=0;ifillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev); +} + DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair >& fieldNames):_arrs(fieldNames.size()) { std::size_t sz(fieldNames.size()); @@ -141,6 +241,136 @@ void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::ve (*it).second->spillInfoOnComponents(compNames); } +bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const +{ + int ret(0); + for(std::vector< std::pair > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++,ret++) + { + if((*it).first==m) + { + pos=ret; + return true; + } + } + return false; +} + +const DataArrayDoubleCollection& MEDCouplingGridCollection::retrieveFieldsAt(int pos) const +{ + if(pos<0 || pos>(int)_map_of_dadc.size()) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::retrieveFieldsAt : invalid pos given in input ! Must be in [0,size) !"); + return *_map_of_dadc[pos].second; +} + +void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse) +{ + if(!fine || !coarse) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : one or more input pointer is NULL !"); + const std::vector< std::pair > >& mf(fine->_map_of_dadc); + const std::vector< std::pair > >& mc(coarse->_map_of_dadc); + for(std::vector< std::pair > >::const_iterator it=mf.begin();it!=mf.end();it++) + { + const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first); + const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather()); + bool found(false); + for(std::vector< std::pair > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++) + { + if((*it0).first==fatherOfFineMesh) + { + found=true; + int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh)); + const DataArrayDoubleCollection *coarseDaCol((*it0).second); + DataArrayDoubleCollection *coarseModified(const_cast(coarseDaCol));//coarse values in DataArrayDouble will be altered + DataArrayDoubleCollection::SynchronizeFineToCoarse(ghostLev,fatherOfFineMesh,patchId,(*it).second,coarseModified); + } + } + if(!found) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeFineToCoarse : a fine mesh is orphan regarding given coarse meshes !"); + } +} + +void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine) +{ + if(!fine || !coarse) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : one or more input pointer is NULL !"); + const std::vector< std::pair > >& mf(fine->_map_of_dadc); + const std::vector< std::pair > >& mc(coarse->_map_of_dadc); + for(std::vector< std::pair > >::const_iterator it=mf.begin();it!=mf.end();it++) + { + const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first); + const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather()); + bool found(false); + for(std::vector< std::pair > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++) + { + if((*it0).first==fatherOfFineMesh) + { + found=true; + int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh)); + const DataArrayDoubleCollection *fineDaCol((*it).second); + DataArrayDoubleCollection *fineModified(const_cast(fineDaCol));//fine values in DataArrayDouble will be altered + DataArrayDoubleCollection::SynchronizeCoarseToFine(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified); + } + } + if(!found) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFine : a fine mesh is orphan regarding given coarse meshes !"); + } +} + +void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev) const +{ + std::map > > m; + for(std::vector< std::pair > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++) + { + const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first); + const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather()); + m[fatherOfFineMesh].push_back(std::pair(fineMesh,(*it).second)); + } + for(std::map > >::const_iterator it0=m.begin();it0!=m.end();it0++) + { + std::size_t sz((*it0).second.size()); + std::vector v0(sz); + std::vector v1(sz); + for(std::size_t i=0;i(tmp); + } + for(std::vector >::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++) + { + int patchId((*it0).first->getPatchIdFromChildMesh((*it1).first)); + DataArrayDoubleCollection::SynchronizeFineEachOther(patchId,ghostLev,(*it0).first,v0,v1); + } + } +} + +void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine) +{ + if(!fine || !coarse) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : one or more input pointer is NULL !"); + const std::vector< std::pair > >& mf(fine->_map_of_dadc); + const std::vector< std::pair > >& mc(coarse->_map_of_dadc); + for(std::vector< std::pair > >::const_iterator it=mf.begin();it!=mf.end();it++) + { + const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first); + const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather()); + bool found(false); + for(std::vector< std::pair > >::const_iterator it0=mc.begin();it0!=mc.end() && !found;it0++) + { + if((*it0).first==fatherOfFineMesh) + { + found=true; + int patchId(fatherOfFineMesh->getPatchIdFromChildMesh(fineMesh)); + const DataArrayDoubleCollection *fineDaCol((*it).second); + DataArrayDoubleCollection *fineModified(const_cast(fineDaCol));//fine values in DataArrayDouble will be altered + DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,fatherOfFineMesh,patchId,(*it0).second,fineModified); + } + } + if(!found) + throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone : a fine mesh is orphan regarding given coarse meshes !"); + } +} + MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector& ms, const std::vector< std::pair >& fieldNames):_map_of_dadc(ms.size()) { std::size_t sz(ms.size()); @@ -193,6 +423,22 @@ MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMes return new MEDCouplingAMRAttribute(gf,fieldNames); } +MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair > >& fieldNames) +{ + std::size_t sz(fieldNames.size()); + std::vector< std::pair > fieldNames2(sz); + std::vector< std::vector > compNames(sz); + for(std::size_t i=0;i ret(New(gf,fieldNames2)); + ret->spillInfoOnComponents(compNames); + return ret.retn(); +} + /*! * Assign the info on components for all DataArrayDouble instance recursively stored in \a this. * The first dim of input \a compNames is the field id in the same order than those implicitely specified in \a fieldNames parameter of MEDCouplingAMRAttribute::New. @@ -206,6 +452,115 @@ void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vect (*it)->spillInfoOnComponents(compNames); } +/*! + * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh. + * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown. + * + * \return std::vector - DataArrayDouble instances to be deallocated by the caller (using decrRef). + * \sa retrieveFieldOn + */ +std::vector MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_levs.begin();it!=_levs.end();it++) + { + int tmp(-1); + if((*it)->presenceOf(mesh,tmp)) + { + const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp)); + return ddc.retrieveFields(); + } + } + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldsOn : the mesh specified is not in the progeny of this !"); +} + +/*! + * \sa retrieveFieldsOn + */ +DataArrayDouble *MEDCouplingAMRAttribute::retrieveFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_levs.begin();it!=_levs.end();it++) + { + int tmp(-1); + if((*it)->presenceOf(mesh,tmp)) + { + const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp)); + return ddc.retrieveFieldWithName(fieldName); + } + } + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !"); +} + +/*! + * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using + * MEDCouplingAMRAttribute::alloc method. + */ +void MEDCouplingAMRAttribute::synchronizeFineToCoarse(int ghostLev) +{ + if(_levs.empty()) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !"); + std::size_t sz(_levs.size()); + // + while(sz>1) + { + sz--; + const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]); + MEDCouplingGridCollection::SynchronizeFineToCoarse(ghostLev,fine,coarse); + } +} + +/*! + * This method synchronizes from coarse to fine arrays and fine to fine each other (if ghostLev is >0). This method makes the hypothesis that \a this has been allocated before using + * MEDCouplingAMRAttribute::alloc method. + */ +void MEDCouplingAMRAttribute::synchronizeCoarseToFine(int ghostLev) +{ + if(_levs.empty()) + throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !"); + std::size_t sz(_levs.size()); + // + for(std::size_t i=1;isynchronizeFineEachOther(ghostLev); + } +} + /*! * This method allocates all DataArrayDouble instances stored recursively in \a this. * diff --git a/src/MEDCoupling/MEDCouplingAMRAttribute.hxx b/src/MEDCoupling/MEDCouplingAMRAttribute.hxx index 6651aa416..2fe0fdda3 100644 --- a/src/MEDCoupling/MEDCouplingAMRAttribute.hxx +++ b/src/MEDCoupling/MEDCouplingAMRAttribute.hxx @@ -34,6 +34,12 @@ namespace ParaMEDMEM void allocTuples(int nbOfTuples); void dellocTuples(); void spillInfoOnComponents(const std::vector< std::vector >& compNames); + std::vector retrieveFields() const; + DataArrayDouble *retrieveFieldWithName(const std::string& name) const; + static void SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse); + static void SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine); + static void SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector& children, const std::vector& fieldsOnFine); + static void SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine); private: DataArrayDoubleCollection(const std::vector< std::pair >& fieldNames); std::size_t getHeapMemorySizeWithoutChildren() const; @@ -51,6 +57,12 @@ namespace ParaMEDMEM void alloc(int ghostLev); void dealloc(); void spillInfoOnComponents(const std::vector< std::vector >& compNames); + bool presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const; + const DataArrayDoubleCollection& retrieveFieldsAt(int pos) const; + static void SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse); + static void SynchronizeCoarseToFine(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine); + void synchronizeFineEachOther(int ghostLev) const; + static void SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine); private: MEDCouplingGridCollection(const std::vector& ms, const std::vector< std::pair >& fieldNames); std::size_t getHeapMemorySizeWithoutChildren() const; @@ -65,8 +77,15 @@ namespace ParaMEDMEM { public: MEDCOUPLING_EXPORT static MEDCouplingAMRAttribute *New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair >& fieldNames); + MEDCOUPLING_EXPORT static MEDCouplingAMRAttribute *New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair > >& fieldNames); MEDCOUPLING_EXPORT void spillInfoOnComponents(const std::vector< std::vector >& compNames); + MEDCOUPLING_EXPORT std::vector retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const; + MEDCOUPLING_EXPORT DataArrayDouble *retrieveFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const; // + MEDCOUPLING_EXPORT void synchronizeFineToCoarse(int ghostLev); + MEDCOUPLING_EXPORT void synchronizeCoarseToFine(int ghostLev); + MEDCOUPLING_EXPORT void synchronizeCoarseToFineOnlyInGhostZone(int ghostLev); + MEDCOUPLING_EXPORT void synchronizeFineEachOtherInGhostZone(int ghostLev); MEDCOUPLING_EXPORT void alloc(int ghostLev); MEDCOUPLING_EXPORT void dealloc(); MEDCOUPLING_EXPORT bool changeGodFather(MEDCouplingCartesianAMRMesh *gf); diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx index 0208d7425..34aec9711 100644 --- a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx +++ b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.cxx @@ -249,6 +249,10 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const /*! * This method returns the max number of cells covering all the space without overlapping. + * It returns the number of cells of the mesh with the highest resolution. + * The returned value is equal to the number of cells of mesh returned by buildUnstructured. + * + * \sa buildUnstructured */ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const { @@ -680,6 +684,17 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const return (int)_patches.size(); } +int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const +{ + int ret(0); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++) + { + if((*it)->getMesh()==mesh) + return ret; + } + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !"); +} + const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const { checkPatchId(patchId); @@ -771,6 +786,23 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, cons MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev); } +/*! + * This method is equivalent to fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated + * in \a cellFieldOnPatch. + * + * \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 \b only \b in \b the \b ghost \b zone. + * \param [in] ghostLev - The size of the ghost zone (must be >=0 !) + */ +void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const +{ + if(!cellFieldOnThis || !cellFieldOnThis->isAllocated()) + throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !"); + const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId)); + MEDCouplingIMesh::SpreadCoarseToFineGhostZone(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. @@ -797,6 +829,10 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, c fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches); } +/*! + * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone. + * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const. + */ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector& arrsOnPatches) const { int nbp(getNumberOfPatches()),dim(getSpaceDimension()); @@ -1173,6 +1209,6 @@ void MEDCouplingCartesianAMRMesh::checkData() const MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh() { MEDCouplingDataForGodFather *data(_data); - if(!data) + if(data) data->changeGodFather(0); } diff --git a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.hxx b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.hxx index 272b81028..6fbb657ba 100644 --- a/src/MEDCoupling/MEDCouplingCartesianAMRMesh.hxx +++ b/src/MEDCoupling/MEDCouplingCartesianAMRMesh.hxx @@ -98,6 +98,10 @@ namespace ParaMEDMEM { friend class MEDCouplingCartesianAMRMesh; public: + MEDCOUPLING_EXPORT virtual void synchronizeFineToCoarse(int ghostLev) = 0; + MEDCOUPLING_EXPORT virtual void synchronizeCoarseToFine(int ghostLev) = 0; + MEDCOUPLING_EXPORT virtual void synchronizeCoarseToFineOnlyInGhostZone(int ghostLev) = 0; + MEDCOUPLING_EXPORT virtual void synchronizeFineEachOtherInGhostZone(int ghostLev) = 0; MEDCOUPLING_EXPORT virtual void alloc(int ghostLev) = 0; MEDCOUPLING_EXPORT virtual void dealloc() = 0; protected: @@ -140,15 +144,22 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void removeAllPatches(); MEDCOUPLING_EXPORT void removePatch(int patchId); MEDCOUPLING_EXPORT int getNumberOfPatches() const; + MEDCOUPLING_EXPORT int getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) 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; + // coarse to fine 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 fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const; + // coarse to fine + fine to fine MEDCOUPLING_EXPORT void fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector& arrsOnPatches) const; + // fine to fine MEDCOUPLING_EXPORT void fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector& arrsOnPatches) const; + // fine to coarse 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; diff --git a/src/MEDCoupling/MEDCouplingIMesh.cxx b/src/MEDCoupling/MEDCouplingIMesh.cxx index 6ec8c5839..4b7d62815 100644 --- a/src/MEDCoupling/MEDCouplingIMesh.cxx +++ b/src/MEDCoupling/MEDCouplingIMesh.cxx @@ -592,7 +592,8 @@ void MEDCouplingIMesh::SpreadCoarseToFine(const DataArrayDouble *coarseDA, const * \param [in] fineLocInCoarse The cell localization of refined mesh into the coarse one. * \param [in] facts The refinement coefficient per axis. * \param [in] ghostSize - The size of the ghost zone. The ghost zone is expected to be the same for all axis and both for coarse and fine meshes. - * \sa CondenseFineToCoarse + * + * \sa CondenseFineToCoarse,SpreadCoarseToFineGhostZone */ void MEDCouplingIMesh::SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, int ghostSize) { @@ -670,7 +671,7 @@ void MEDCouplingIMesh::SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, { for(int ig=0;ig= ghostlev for(int i=0;i& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, int ghostSize) +{ + if(ghostSize<0) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhostZone : ghost level has to be >= 0 !"); + if(coarseSt.size()!=fineLocInCoarse.size() || coarseSt.size()!=facts.size()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhostZone : All input vectors (dimension) must have the same size !"); + if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhostZone : 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)); + int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseStG)); + int nbCompo(fineDA->getNumberOfComponents()); + if(coarseDA->getNumberOfComponents()!=nbCompo) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhostZone : the number of components of fine DA and coarse one mismatches !"); + if(meshDim!=(int)fineLocInCoarse.size() || meshDim!=(int)facts.size()) + throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFineGhostZone : 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::SpreadCoarseToFineGhostZone : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + // + 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::SpreadCoarseToFineGhostZone : 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()); + // + std::vector dims(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse)); + switch(meshDim) + { + case 1: + { + int offset(fineLocInCoarse[0].first+ghostSize-1),fact0(facts[0]);//offset is always >=0 thanks to the fact that ghostSize>=1 ! + for(int i=0;i=0 thanks to the fact that ghostSize>=1 ! + for(int jg=0;jg= ghostlev + outPtr+=fact0*nbCompo*dims[0]; + for(int ig=0;ig& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, DataArrayDouble *coarseDA, int ghostSize); MEDCOUPLING_EXPORT static void SpreadCoarseToFine(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts); MEDCOUPLING_EXPORT static void SpreadCoarseToFineGhost(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, int ghostSize); + MEDCOUPLING_EXPORT static void SpreadCoarseToFineGhostZone(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair >& fineLocInCoarse, const std::vector& facts, int ghostSize); // MEDCOUPLING_EXPORT MEDCouplingMesh *deepCpy() const; MEDCOUPLING_EXPORT MEDCouplingIMesh *clone(bool recDeepCpy) const; diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index b72ee4c40..3fa76fadb 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -41,6 +41,7 @@ #include "MEDCouplingDefinitionTime.hxx" #include "MEDCouplingFieldDiscretization.hxx" #include "MEDCouplingCartesianAMRMesh.hxx" +#include "MEDCouplingAMRAttribute.hxx" #include "MEDCouplingMatrix.hxx" #include "MEDCouplingTypemaps.i" @@ -94,6 +95,13 @@ using namespace INTERP_KERNEL; } //$$$$$$$$$$$$$$$$$$ +//////////////////// +%typemap(out) MEDCouplingDataForGodFather* +{ + $result=convertDataForGodFather($1,$owner); +} +//$$$$$$$$$$$$$$$$$$ + //////////////////// %typemap(out) ParaMEDMEM::MEDCoupling1GTUMesh* { @@ -344,6 +352,8 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::New; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getDataConst; %newobject ParaMEDMEM::MEDCouplingCartesianAMRMesh::getData; +%newobject ParaMEDMEM::MEDCouplingAMRAttribute::New; +%newobject ParaMEDMEM::MEDCouplingAMRAttribute::retrieveFieldOn; %newobject ParaMEDMEM::DenseMatrix::New; %newobject ParaMEDMEM::DenseMatrix::deepCpy; %newobject ParaMEDMEM::DenseMatrix::shallowCpy; @@ -381,6 +391,7 @@ using namespace INTERP_KERNEL; %feature("unref") MEDCouplingCartesianAMRPatchGF "$this->decrRef();" %feature("unref") MEDCouplingCartesianAMRPatch "$this->decrRef();" %feature("unref") MEDCouplingDataForGodFather "$this->decrRef();" +%feature("unref") MEDCouplingAMRAttribute "$this->decrRef();" %feature("unref") DenseMatrix "$this->decrRef();" %rename(assign) *::operator=; @@ -3219,6 +3230,13 @@ namespace ParaMEDMEM MEDCouplingIMesh::SpreadCoarseToFineGhost(coarseDA,coarseSt,fineDA,inp,facts,ghostSize); } + static void SpreadCoarseToFineGhostZone(const DataArrayDouble *coarseDA, const std::vector& coarseSt, DataArrayDouble *fineDA, PyObject *fineLocInCoarse, const std::vector& facts, int ghostSize) throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > inp; + convertPyToVectorPairInt(fineLocInCoarse,inp); + MEDCouplingIMesh::SpreadCoarseToFineGhostZone(coarseDA,coarseSt,fineDA,inp,facts,ghostSize); + } + std::string __str__() const throw(INTERP_KERNEL::Exception) { return self->simpleRepr(); @@ -4838,7 +4856,11 @@ namespace ParaMEDMEM class MEDCouplingDataForGodFather : public RefCountObject { public: - virtual void alloc() throw(INTERP_KERNEL::Exception); + virtual void synchronizeFineToCoarse(int ghostLev) throw(INTERP_KERNEL::Exception); + virtual void synchronizeCoarseToFine(int ghostLev) throw(INTERP_KERNEL::Exception); + virtual void synchronizeCoarseToFineOnlyInGhostZone(int ghostLev) throw(INTERP_KERNEL::Exception); + virtual void synchronizeFineEachOtherInGhostZone(int ghostLev) throw(INTERP_KERNEL::Exception); + virtual void alloc(int ghostLev) throw(INTERP_KERNEL::Exception); virtual void dealloc() throw(INTERP_KERNEL::Exception); }; @@ -4856,7 +4878,8 @@ namespace ParaMEDMEM 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); + int getNumberOfPatches() const throw(INTERP_KERNEL::Exception); + int getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const throw(INTERP_KERNEL::Exception); MEDCouplingUMesh *buildUnstructured() const throw(INTERP_KERNEL::Exception); MEDCoupling1SGTUMesh *buildMeshFromPatchEnvelop() const throw(INTERP_KERNEL::Exception); MEDCoupling1SGTUMesh *buildMeshOfDirectChildrenOnly() const throw(INTERP_KERNEL::Exception); @@ -4867,6 +4890,7 @@ namespace ParaMEDMEM 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 fillCellFieldOnPatchOnlyOnGhostZone(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); @@ -4970,7 +4994,7 @@ namespace ParaMEDMEM { public: void setData(MEDCouplingDataForGodFather *data) throw(INTERP_KERNEL::Exception); - void allocData() const throw(INTERP_KERNEL::Exception); + void allocData(int ghostLev) const throw(INTERP_KERNEL::Exception); void deallocData() const throw(INTERP_KERNEL::Exception); %extend { @@ -5015,6 +5039,55 @@ namespace ParaMEDMEM } } }; + + class MEDCouplingAMRAttribute : public MEDCouplingDataForGodFather, public TimeLabel + { + public: + DataArrayDouble *retrieveFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const throw(INTERP_KERNEL::Exception); + bool changeGodFather(MEDCouplingCartesianAMRMesh *gf) throw(INTERP_KERNEL::Exception); + %extend + { + static MEDCouplingAMRAttribute *New(MEDCouplingCartesianAMRMesh *gf, PyObject *fieldNames) throw(INTERP_KERNEL::Exception) + { + std::vector< std::pair > fieldNamesCpp0; + std::vector< std::pair > > fieldNamesCpp1; + MEDCouplingAMRAttribute *ret(0); + try + { + convertPyToVectorPairStringInt(fieldNames,fieldNamesCpp0); + ret=MEDCouplingAMRAttribute::New(gf,fieldNamesCpp0); + } + catch(INTERP_KERNEL::Exception&) + { + convertPyToVectorPairStringVecString(fieldNames,fieldNamesCpp1); + ret=MEDCouplingAMRAttribute::New(gf,fieldNamesCpp1); + } + return ret; + } + + MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, PyObject *fieldNames) throw(INTERP_KERNEL::Exception) + { + return ParaMEDMEM_MEDCouplingAMRAttribute_New(gf,fieldNames); + } + + void spillInfoOnComponents(PyObject *compNames) throw(INTERP_KERNEL::Exception) + { + std::vector< std::vector > compNamesCpp; + convertPyToVectorOfVectorOfString(compNames,compNamesCpp); + self->spillInfoOnComponents(compNamesCpp); + } + + PyObject *retrieveFieldsOn(MEDCouplingCartesianAMRMeshGen *mesh) const throw(INTERP_KERNEL::Exception) + { + std::vector ret(self->retrieveFieldsOn(mesh)); + int sz((int)ret.size()); + PyObject *retPy(PyList_New(sz)); + for(int i=0;i >& arr) throw(INTERP_KERNEL::Exception) +{ + const char msg[]="convertPyToVectorPairStringInt : list must contain tuples of 2 integers only or tuple must contain tuples of 1 string and 1 integer only !"; + if(PyList_Check(pyLi)) + { + int size=PyList_Size(pyLi); + arr.resize(size); + for(int i=0;i& arr) throw(INTERP_KERNEL::Exception) { if(PyList_Check(pyLi)) @@ -957,6 +1014,93 @@ static bool fillStringVector(PyObject *pyLi, std::vector& vec) thro else return false; } +static void convertPyToVectorOfVectorOfString(PyObject *pyLi, std::vector< std::vector >& arr) throw(INTERP_KERNEL::Exception) +{ + const char msg[]="convertPyToVectorOfVectorOfString : expecting list of list of strings !"; + if(PyList_Check(pyLi)) + { + Py_ssize_t sz=PyList_Size(pyLi); + arr.resize(sz); + for(int i=0;i > >& arr) throw(INTERP_KERNEL::Exception) +{ + const char msg[]="convertPyToVectorPairStringVecString : expecting list of tuples containing each exactly 2 items : one string and one vector of string !"; + if(PyList_Check(pyLi)) + { + Py_ssize_t sz=PyList_Size(pyLi); + arr.resize(sz); + for(int i=0;i > item; + PyObject *o_0=PyTuple_GetItem(o,0); + if(!PyString_Check(o_0)) + throw INTERP_KERNEL::Exception(msg); + item.first=PyString_AsString(o_0); + PyObject *o_1=PyTuple_GetItem(o,1); + if(!fillStringVector(o_1,item.second)) + throw INTERP_KERNEL::Exception(msg); + arr[i]=item; + } + else + throw INTERP_KERNEL::Exception(msg); + } + } + else if(PyTuple_Check(pyLi)) + { + Py_ssize_t sz=PyTuple_Size(pyLi); + arr.resize(sz); + for(int i=0;i > item; + PyObject *o_0=PyTuple_GetItem(o,0); + if(!PyString_Check(o_0)) + throw INTERP_KERNEL::Exception(msg); + item.first=PyString_AsString(o_0); + PyObject *o_1=PyTuple_GetItem(o,1); + if(!fillStringVector(o_1,item.second)) + throw INTERP_KERNEL::Exception(msg); + arr[i]=item; + } + else + throw INTERP_KERNEL::Exception(msg); + } + } + else + throw INTERP_KERNEL::Exception(msg); +} static PyObject *convertDblArrToPyList(const double *ptr, int size) throw(INTERP_KERNEL::Exception) { diff --git a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i index 0a50f88f8..edae65742 100644 --- a/src/MEDCoupling_Swig/MEDCouplingTypemaps.i +++ b/src/MEDCoupling_Swig/MEDCouplingTypemaps.i @@ -103,6 +103,20 @@ static PyObject *convertCartesianAMRMesh(ParaMEDMEM::MEDCouplingCartesianAMRMesh throw INTERP_KERNEL::Exception("convertCartesianAMRMesh wrap : unrecognized type of cartesian AMR mesh !"); } +static PyObject *convertDataForGodFather(ParaMEDMEM::MEDCouplingDataForGodFather *data, int owner) throw(INTERP_KERNEL::Exception) +{ + if(!data) + { + Py_XINCREF(Py_None); + return Py_None; + } + if(dynamic_cast(data)) + { + return SWIG_NewPointerObj(reinterpret_cast(data),SWIGTYPE_p_ParaMEDMEM__MEDCouplingAMRAttribute,owner); + } + throw INTERP_KERNEL::Exception("convertDataForGodFather wrap : unrecognized data type for AMR !"); +} + static PyObject *convertCartesianAMRPatch(ParaMEDMEM::MEDCouplingCartesianAMRPatchGen *patch, int owner) throw(INTERP_KERNEL::Exception) { if(!patch)