From c90ac07d607aca9c357cee7649613a386ecc0924 Mon Sep 17 00:00:00 2001 From: ageay Date: Tue, 18 Dec 2012 09:15:37 +0000 Subject: [PATCH] Improvement of perf of zipConnectivityTraducer. --- src/MEDCoupling/MEDCouplingUMesh.cxx | 108 +++--------------- src/MEDCoupling/MEDCouplingUMesh.hxx | 4 +- src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 4 + src/MEDCoupling_Swig/MEDCouplingCommon.i | 13 ++- 4 files changed, 32 insertions(+), 97 deletions(-) diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index 588456b08..5a0c387e2 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -1408,63 +1408,6 @@ bool MEDCouplingUMesh::areCellsEqualInPool(const std::vector& candidates, i return ret; } -/*! - * This method common cells base regarding 'compType' comparison policy described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for details. - * This method returns 2 values 'res' and 'resI'. - * If 'res' and 'resI' are not empty before calling this method they will be cleared before set. - * The format of 'res' and 'resI' is as explained here. - * resI.size()-1 is the number of set of cells equal. - * The nth set is [res.begin()+resI[n];res.begin()+resI[n+1]) with 0<=n -void MEDCouplingUMesh::findCommonCellsBase(int startCellId, int compType, std::vector& res, std::vector& resI) const -{ - res.clear(); resI.clear(); - resI.push_back(0); - std::vector bbox; - int nbOfCells=getNumberOfCells(); - getBoundingBoxForBBTree(bbox); - double bb[2*SPACEDIM]; - double eps=getCaracteristicDimension(); - eps*=1.e-12; - BBTree myTree(&bbox[0],0,0,nbOfCells,-eps); - const int *conn=getNodalConnectivity()->getConstPointer(); - const int *connI=getNodalConnectivityIndex()->getConstPointer(); - const double *coords=getCoords()->getConstPointer(); - std::vector isFetched(nbOfCells); - for(int k=startCellId;k::max(); bb[2*j+1]=-std::numeric_limits::max(); } - for(const int *pt=conn+connI[k]+1;pt!=conn+connI[k+1];pt++) - if(*pt>-1) - { - for(int j=0;j candidates1; - myTree.getIntersectingElems(bb,candidates1); - std::vector candidates; - for(std::vector::const_iterator iter=candidates1.begin();iter!=candidates1.end();iter++) - if(!isFetched[*iter]) - candidates.push_back(*iter); - if(areCellsEqualInPool(candidates,compType,res)) - { - int pos=resI.back(); - resI.push_back((int)res.size()); - for(std::vector::const_iterator it=res.begin()+pos;it!=res.end();it++) - isFetched[*it]=true; - } - isFetched[k]=true; - } - } -} - /*! * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType. * This method keeps the coordiantes of \a this. This method is time consuming and is called @@ -1476,16 +1419,17 @@ void MEDCouplingUMesh::findCommonCellsBase(int startCellId, int compType, std::v * - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy * can be used for users not sensitive to orientation of cell * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned. - * \param [out] newNbOfCells + * \param [out] commonCells + * \param [out] commonCellsI * \return the correspondance array old to new in a newly allocated array. * */ -DataArrayInt *MEDCouplingUMesh::findEqualCells(int compType, int startCellId, int& newNbOfCells) const throw(INTERP_KERNEL::Exception) +void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, std::vector& commonCells, std::vector& commonCellsI) const throw(INTERP_KERNEL::Exception) { checkConnectivityFullyDefined(); int nbOfCells=getNumberOfCells(); - std::vector commonCells; - std::vector commonCellsI(1,0); + commonCells.clear(); + commonCellsI.resize(1); commonCellsI[0]=0; MEDCouplingAutoRefCountObjectPtr revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New(); getReverseNodalConnectivity(revNodal,revNodalI); const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer(); @@ -1559,10 +1503,6 @@ DataArrayInt *MEDCouplingUMesh::findEqualCells(int compType, int startCellId, in } } } - MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCells,&commonCells[0],&commonCellsI[0], - &commonCellsI[0]+commonCellsI.size(),newNbOfCells); - ret->incrRef(); - return ret; } /*! @@ -1583,8 +1523,11 @@ DataArrayInt *MEDCouplingUMesh::findEqualCells(int compType, int startCellId, in */ DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception) { + std::vector commonCells,commonCellsI; + findCommonCells(compType,startCellId,commonCells,commonCellsI); int newNbOfCells=-1; - MEDCouplingAutoRefCountObjectPtr ret=findEqualCells(compType,startCellId,newNbOfCells); + MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),&commonCells[0],&commonCellsI[0], + &commonCellsI[0]+commonCellsI.size(),newNbOfCells); MEDCouplingAutoRefCountObjectPtr ret2=ret->invertArrayO2N2N2O(newNbOfCells); MEDCouplingAutoRefCountObjectPtr self=static_cast(buildPartOfMySelf(ret2->begin(),ret2->end(),true)); setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true); @@ -1607,6 +1550,14 @@ bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int com { MEDCouplingAutoRefCountObjectPtr mesh=MergeUMeshesOnSameCoords(this,other); int nbOfCells=getNumberOfCells(); + static const int possibleCompType[]={0,1,2}; + if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int)) + { + std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : "; + std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator(oss," ")); + oss << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } MEDCouplingAutoRefCountObjectPtr o2n=mesh->zipConnectivityTraducer(compType,nbOfCells); arr=o2n->substr(nbOfCells); arr->setName(other->getName()); @@ -1628,30 +1579,9 @@ bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int com bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr mesh=MergeUMeshesOnSameCoords(this,other); - int spaceDim=mesh->getSpaceDimension(); - std::vector commonCells; - std::vector commonCellsI; + std::vector commonCells,commonCellsI; int thisNbCells=getNumberOfCells(); - switch(spaceDim) - { - case 3: - { - findCommonCellsBase<3>(thisNbCells,7,commonCells,commonCellsI); - break; - } - case 2: - { - findCommonCellsBase<2>(thisNbCells,7,commonCells,commonCellsI); - break; - } - case 1: - { - findCommonCellsBase<1>(thisNbCells,7,commonCells,commonCellsI); - break; - } - default: - throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3."); - } + mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI); int otherNbCells=other->getNumberOfCells(); MEDCouplingAutoRefCountObjectPtr arr2=DataArrayInt::New(); arr2->alloc(otherNbCells,1); diff --git a/src/MEDCoupling/MEDCouplingUMesh.hxx b/src/MEDCoupling/MEDCouplingUMesh.hxx index 4811eb666..1366374c2 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.hxx +++ b/src/MEDCoupling/MEDCouplingUMesh.hxx @@ -109,7 +109,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT DataArrayInt *computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *zipCoordsTraducer() throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT DataArrayInt *zipConnectivityTraducer(int compType, int startCellId=0) throw(INTERP_KERNEL::Exception); - MEDCOUPLING_EXPORT DataArrayInt *findEqualCells(int compType, int startCellId, int& newNbOfCells) const throw(INTERP_KERNEL::Exception); + MEDCOUPLING_EXPORT void findCommonCells(int compType, int startCellId, std::vector& commonCells, std::vector& commonCellsI) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT bool areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception); MEDCOUPLING_EXPORT void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception); @@ -252,8 +252,6 @@ namespace ParaMEDMEM DataArrayDouble *fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception); DataArrayDouble *fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception); DataArrayDouble *fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception); - template - void findCommonCellsBase(int startCellId, int compType, std::vector& res, std::vector& resI) const; bool areCellsEqualInPool(const std::vector& candidates, int compType, std::vector& result) const; MEDCouplingUMesh *buildPartOfMySelfKeepCoords(const int *begin, const int *end) const; MEDCouplingUMesh *buildPartOfMySelfKeepCoords2(int start, int end, int step) const; diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index 614141b6c..0a16344f4 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -5508,6 +5508,10 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertEqual(pt[1],tmp.getIJ(0,1)); ret,tmp=m2.areCellsIncludedIn(m,0) self.assertTrue(not ret); + m3=MEDCouplingUMesh.MergeUMeshesOnSameCoords(m,m2) + c,cI=m3.findCommonCells(2,m.getNumberOfCells()) + self.assertTrue(c.isEqual(DataArrayInt([1,5,3,6]))) + self.assertTrue(cI.isEqual(DataArrayInt([0,2,4]))) pass def testSwigErrorProtection1(self): diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index fdfbffe9f..28f407143 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -1677,13 +1677,16 @@ namespace ParaMEDMEM return res; } - PyObject *findEqualCells(int compType, int startCellId=0) const throw(INTERP_KERNEL::Exception) + PyObject *findCommonCells(int compType, int startCellId=0) const throw(INTERP_KERNEL::Exception) { - int newNbOfCells=-1; - DataArrayInt *ret0=self->findEqualCells(compType,startCellId,newNbOfCells); + std::vector v0,v1; + self->findCommonCells(compType,startCellId,v0,v1); + DataArrayInt *v0a=DataArrayInt::New(),*v1a=DataArrayInt::New(); + v0a->alloc((int)v0.size(),1); std::copy(v0.begin(),v0.end(),v0a->getPointer()); + v1a->alloc((int)v1.size(),1); std::copy(v1.begin(),v1.end(),v1a->getPointer()); PyObject *res = PyList_New(2); - PyList_SetItem(res,0,SWIG_NewPointerObj(SWIG_as_voidptr(ret0),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); - PyList_SetItem(res,1,SWIG_From_int(newNbOfCells)); + PyList_SetItem(res,0,SWIG_NewPointerObj(SWIG_as_voidptr(v0a),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); + PyList_SetItem(res,1,SWIG_NewPointerObj(SWIG_as_voidptr(v1a),SWIGTYPE_p_ParaMEDMEM__DataArrayInt, SWIG_POINTER_OWN | 0 )); return res; } -- 2.39.2