From: Anthony Geay Date: Tue, 30 Sep 2014 12:02:19 +0000 (+0200) Subject: Improve performance on // read of a MED file using block filter for nodes instead... X-Git-Tag: V7_5_0a1~10 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=369c9d5f1cf63fbba60baa84d98868978374ee63;p=modules%2Fmed.git Improve performance on // read of a MED file using block filter for nodes instead of classical filter. --- diff --git a/src/MEDCoupling/MEDCoupling1GTUMesh.cxx b/src/MEDCoupling/MEDCoupling1GTUMesh.cxx index 5c9b32456..a13cb0b4f 100644 --- a/src/MEDCoupling/MEDCoupling1GTUMesh.cxx +++ b/src/MEDCoupling/MEDCoupling1GTUMesh.cxx @@ -1067,12 +1067,27 @@ DataArrayInt *MEDCoupling1SGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const return ret.retn(); } +/*! + * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of + * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range ! + * + * \param [in] offset - specifies the offset to be applied on each element of connectivity. + * + * \sa renumberNodesInConn + */ +void MEDCoupling1SGTUMesh::renumberNodesWithOffsetInConn(int offset) +{ + getNumberOfCells();//only to check that all is well defined. + _conn->applyLin(1,offset); + updateTime(); +} + /*! * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction * of a big mesh. */ -void MEDCoupling1SGTUMesh::renumberNodesInConn(const std::map& newNodeNumbersO2N) +void MEDCoupling1SGTUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N) { getNumberOfCells();//only to check that all is well defined. int *begPtr(_conn->getPointer()); @@ -1080,7 +1095,7 @@ void MEDCoupling1SGTUMesh::renumberNodesInConn(const std::map& newNodeN int *endPtr(begPtr+nbElt); for(int *it=begPtr;it!=endPtr;it++) { - std::map::const_iterator it2(newNodeNumbersO2N.find(*it)); + INTERP_KERNEL::HashMap::const_iterator it2(newNodeNumbersO2N.find(*it)); if(it2!=newNodeNumbersO2N.end()) { *it=(*it2).second; @@ -3093,12 +3108,35 @@ DataArrayInt *MEDCoupling1DGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const return ret.retn(); } +/*! + * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of + * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range ! + * + * \param [in] offset - specifies the offset to be applied on each element of connectivity. + * + * \sa renumberNodesInConn + */ +void MEDCoupling1DGTUMesh::renumberNodesWithOffsetInConn(int offset) +{ + getNumberOfCells();//only to check that all is well defined. + // + int nbElemsIn(getNumberOfNodes()),nbOfTuples(_conn->getNumberOfTuples()); + int *pt(_conn->getPointer()); + for(int i=0;i& newNodeNumbersO2N) +void MEDCoupling1DGTUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N) { getNumberOfCells();//only to check that all is well defined. // @@ -3109,7 +3147,7 @@ void MEDCoupling1DGTUMesh::renumberNodesInConn(const std::map& newNodeN if(*pt==-1) continue; if(*pt>=0 && *pt::const_iterator it(newNodeNumbersO2N.find(*pt)); + INTERP_KERNEL::HashMap::const_iterator it(newNodeNumbersO2N.find(*pt)); if(it!=newNodeNumbersO2N.end()) *pt=(*it).second; else diff --git a/src/MEDCoupling/MEDCoupling1GTUMesh.hxx b/src/MEDCoupling/MEDCoupling1GTUMesh.hxx index 50169f5ab..01c09f0a6 100644 --- a/src/MEDCoupling/MEDCoupling1GTUMesh.hxx +++ b/src/MEDCoupling/MEDCoupling1GTUMesh.hxx @@ -130,7 +130,8 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector& tinyInfo) const; MEDCOUPLING_EXPORT DataArrayInt *computeFetchedNodeIds() const; MEDCOUPLING_EXPORT DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const; - MEDCOUPLING_EXPORT void renumberNodesInConn(const std::map& newNodeNumbersO2N); + MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(int offset); + MEDCOUPLING_EXPORT void renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N); MEDCOUPLING_EXPORT void renumberNodesInConn(const int *newNodeNumbersO2N); MEDCOUPLING_EXPORT void fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const; MEDCOUPLING_EXPORT int getNumberOfNodesInCell(int cellId) const; @@ -222,7 +223,8 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector& tinyInfo) const; MEDCOUPLING_EXPORT DataArrayInt *computeFetchedNodeIds() const; MEDCOUPLING_EXPORT DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const; - MEDCOUPLING_EXPORT void renumberNodesInConn(const std::map& newNodeNumbersO2N); + MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(int offset); + MEDCOUPLING_EXPORT void renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N); MEDCOUPLING_EXPORT void renumberNodesInConn(const int *newNodeNumbersO2N); MEDCOUPLING_EXPORT void fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const; MEDCOUPLING_EXPORT int getNumberOfNodesInCell(int cellId) const; diff --git a/src/MEDCoupling/MEDCouplingPointSet.hxx b/src/MEDCoupling/MEDCouplingPointSet.hxx index 59307c6a8..31083d9e8 100644 --- a/src/MEDCoupling/MEDCouplingPointSet.hxx +++ b/src/MEDCoupling/MEDCouplingPointSet.hxx @@ -24,7 +24,8 @@ #include "MEDCoupling.hxx" #include "MEDCouplingMesh.hxx" -#include +#include "InterpKernelHashMap.hxx" + #include namespace INTERP_KERNEL @@ -124,7 +125,8 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT virtual DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const = 0; MEDCOUPLING_EXPORT virtual void fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const = 0; MEDCOUPLING_EXPORT virtual void renumberNodesInConn(const int *newNodeNumbersO2N) = 0; - MEDCOUPLING_EXPORT virtual void renumberNodesInConn(const std::map& newNodeNumbersO2N) = 0; + MEDCOUPLING_EXPORT virtual void renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N) = 0; + MEDCOUPLING_EXPORT virtual void renumberNodesWithOffsetInConn(int offset) = 0; MEDCOUPLING_EXPORT virtual void renumberNodes(const int *newNodeNumbers, int newNbOfNodes); MEDCOUPLING_EXPORT virtual void renumberNodes2(const int *newNodeNumbers, int newNbOfNodes); MEDCOUPLING_EXPORT virtual bool isEmptyMesh(const std::vector& tinyInfo) const = 0; diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index 41784fb2f..3677ba54d 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -2497,24 +2497,51 @@ void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes); } +/*! + * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of + * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range ! + * + * \param [in] offset - specifies the offset to be applied on each element of connectivity. + * + * \sa renumberNodesInConn + */ +void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset) +{ + checkConnectivityFullyDefined(); + int *conn(getNodalConnectivity()->getPointer()); + const int *connIndex(getNodalConnectivityIndex()->getConstPointer()); + int nbOfCells(getNumberOfCells()); + for(int i=0;i=0)//avoid polyhedron separator + { + node+=offset; + } + } + _nodal_connec->declareAsNew(); + updateTime(); +} + /*! * Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead * of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction * of a big mesh. */ -void MEDCouplingUMesh::renumberNodesInConn(const std::map& newNodeNumbersO2N) +void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N) { checkConnectivityFullyDefined(); int *conn(getNodalConnectivity()->getPointer()); const int *connIndex(getNodalConnectivityIndex()->getConstPointer()); - int nbOfCells=getNumberOfCells(); + int nbOfCells(getNumberOfCells()); for(int i=0;i=0)//avoid polyhedron separator { - std::map::const_iterator it(newNodeNumbersO2N.find(node)); + INTERP_KERNEL::HashMap::const_iterator it(newNodeNumbersO2N.find(node)); if(it!=newNodeNumbersO2N.end()) { node=(*it).second; @@ -2550,7 +2577,7 @@ void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N) checkConnectivityFullyDefined(); int *conn=getNodalConnectivity()->getPointer(); const int *connIndex=getNodalConnectivityIndex()->getConstPointer(); - int nbOfCells=getNumberOfCells(); + int nbOfCells(getNumberOfCells()); for(int i=0;i& newNodeNumbersO2N); + MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(int offset); + MEDCOUPLING_EXPORT void renumberNodesInConn(const INTERP_KERNEL::HashMap& newNodeNumbersO2N); MEDCOUPLING_EXPORT void renumberNodesInConn(const int *newNodeNumbersO2N); MEDCOUPLING_EXPORT void shiftNodeNumbersInConn(int delta); MEDCOUPLING_EXPORT void duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset); diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index 01bc5e64c..e4ddc68ec 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -1052,6 +1052,7 @@ namespace ParaMEDMEM virtual bool isEmptyMesh(const std::vector& tinyInfo) const throw(INTERP_KERNEL::Exception); virtual MEDCouplingPointSet *deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception); virtual DataArrayDouble *getBoundingBoxForBBTree(double arcDetEps=1e-12) const throw(INTERP_KERNEL::Exception); + virtual void renumberNodesWithOffsetInConn(int offset) throw(INTERP_KERNEL::Exception); %extend { std::string __str__() const throw(INTERP_KERNEL::Exception) diff --git a/src/MEDLoader/MEDFileMeshLL.cxx b/src/MEDLoader/MEDFileMeshLL.cxx index 344f61447..a140e971b 100644 --- a/src/MEDLoader/MEDFileMeshLL.cxx +++ b/src/MEDLoader/MEDFileMeshLL.cxx @@ -286,15 +286,13 @@ void MEDFileUMeshL2::loadPart(med_idt fid, int mId, const std::string& mName, co for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > >::const_iterator it0=_per_type_mesh.begin();it0!=_per_type_mesh.end();it0++) for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++) (*it1)->getMesh()->computeNodeIdsAlg(fetchedNodeIds); - MEDCouplingAutoRefCountObjectPtr n2o(DataArrayInt::BuildListOfSwitchedOn(fetchedNodeIds)); - std::map o2n; - int newId(0); - for(const int *it0=n2o->begin();it0!=n2o->end();it0++,newId++) - o2n[*it0]=newId; + int nMin(std::distance(fetchedNodeIds.begin(),std::find(fetchedNodeIds.begin(),fetchedNodeIds.end(),true))); + int nMax(std::distance(fetchedNodeIds.rbegin(),std::find(fetchedNodeIds.rbegin(),fetchedNodeIds.rend(),true))); + nMax=nCoords-nMax-1; for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr > >::const_iterator it0=_per_type_mesh.begin();it0!=_per_type_mesh.end();it0++) for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++) - (*it1)->getMesh()->renumberNodesInConn(o2n); - loadPartCoords(fid,mId,infosOnComp,mName,dt,it,n2o); + (*it1)->getMesh()->renumberNodesWithOffsetInConn(-nMin); + loadPartCoords(fid,mId,infosOnComp,mName,dt,it,nMin,nMax); } void MEDFileUMeshL2::loadConnectivity(med_idt fid, int mdim, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) @@ -367,27 +365,22 @@ void MEDFileUMeshL2::loadCoords(med_idt fid, int mId, const std::vectorsetInfoOnComponent(i,infosOnComp[i]); } -/*! - * \param [in] n2o - List all ids to be selected. \b WARNING it is an input parameter \b but non const because the array is modified during the treatment of this - * method. But at the end of the method the state is the same as those before entering in the method (except time label !). This is the consequence of FORTRAN <-> C mode. - */ -void MEDFileUMeshL2::loadPartCoords(med_idt fid, int mId, const std::vector& infosOnComp, const std::string& mName, int dt, int it, DataArrayInt *n2o) +void MEDFileUMeshL2::loadPartCoords(med_idt fid, int mId, const std::vector& infosOnComp, const std::string& mName, int dt, int it, int nMin, int nMax) { - if(!n2o || !n2o->isAllocated() || n2o->getNumberOfComponents()!=1) - throw INTERP_KERNEL::Exception("MEDFileUMeshL2::loadPartCoords : n2o must be not NULL and allocated and with one component !"); med_bool changement,transformation; - int spaceDim((int)infosOnComp.size()),nbNodesToLoad(n2o->getNumberOfTuples()),nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation)); + int spaceDim((int)infosOnComp.size()),nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation)); _coords=DataArrayDouble::New(); + int nbNodesToLoad(nMax-nMin+1); _coords->alloc(nbNodesToLoad,spaceDim); med_filter filter=MED_FILTER_INIT,filter2=MED_FILTER_INIT; - n2o->applyLin(1,1);//C -> FORTRAN - MEDfilterEntityCr(fid,/*nentity*/nCoords,/*nvaluesperentity*/1,/*nconstituentpervalue*/spaceDim, - /*constituentselect*/MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE, - /*profilename*/MED_NO_PROFILE,/*filterarraysize*/nbNodesToLoad,/*filterarray*/n2o->begin(),&filter); + MEDfilterBlockOfEntityCr(fid,/*nentity*/nCoords,/*nvaluesperentity*/1,/*nconstituentpervalue*/spaceDim, + MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE, + /*start*/nMin+1,/*stride*/1,/*count*/1,/*blocksize*/nbNodesToLoad, + /*lastblocksize=useless because count=1*/0,&filter); MEDmeshNodeCoordinateAdvancedRd(fid,mName.c_str(),dt,it,&filter,_coords->getPointer()); MEDfilterClose(&filter); - MEDfilterEntityCr(fid,nCoords,1,1,MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE, - MED_NO_PROFILE,nbNodesToLoad,n2o->begin(),&filter2); + MEDfilterBlockOfEntityCr(fid,nCoords,1,1,MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE, + MED_NO_PROFILE,nMin+1,1,1,nbNodesToLoad,0,&filter2); if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0) { _fam_coords=DataArrayInt::New(); @@ -413,7 +406,6 @@ void MEDFileUMeshL2::loadPartCoords(med_idt fid, int mId, const std::vectorapplyLin(1,-1);//FORTRAN -> C MEDfilterClose(&filter2); _coords->setInfoOnComponents(infosOnComp); } diff --git a/src/MEDLoader/MEDFileMeshLL.hxx b/src/MEDLoader/MEDFileMeshLL.hxx index d2863a507..8cdcc988f 100644 --- a/src/MEDLoader/MEDFileMeshLL.hxx +++ b/src/MEDLoader/MEDFileMeshLL.hxx @@ -76,7 +76,7 @@ namespace ParaMEDMEM void loadConnectivity(med_idt fid, int mdim, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs); void loadPartOfConnectivity(med_idt fid, int mdim, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs); void loadCoords(med_idt fid, int mId, const std::vector& infosOnComp, const std::string& mName, int dt, int it); - void loadPartCoords(med_idt fid, int mId, const std::vector& infosOnComp, const std::string& mName, int dt, int it, DataArrayInt *n2o); + void loadPartCoords(med_idt fid, int mId, const std::vector& infosOnComp, const std::string& mName, int dt, int it, int nMin, int nMax); int getNumberOfLevels() const { return _per_type_mesh.size(); } bool emptyLev(int levId) const { return _per_type_mesh[levId].empty(); } const std::vector< MEDCouplingAutoRefCountObjectPtr >& getLev(int levId) const { return _per_type_mesh[levId]; }