From 1dbce53ac0a3da569f5074fdf92cfd46b221a6ed Mon Sep 17 00:00:00 2001 From: ageay Date: Tue, 23 Jul 2013 09:52:21 +0000 Subject: [PATCH] MEDCouplingStructuredMesh.IsPartStructured MEDCouplingStructuredMesh.BuildExplicitIdsFrom - behaviour modification MEDCouplingStructuredMesh::buildPartAndReduceNodes returns a structured mesh if possible to reduce the cost in memory --- src/MEDCoupling/MEDCouplingCMesh.cxx | 25 +++ src/MEDCoupling/MEDCouplingCMesh.hxx | 2 + .../MEDCouplingCurveLinearMesh.cxx | 31 +++ .../MEDCouplingCurveLinearMesh.hxx | 1 + src/MEDCoupling/MEDCouplingStructuredMesh.cxx | 186 +++++++++++++++++- src/MEDCoupling/MEDCouplingStructuredMesh.hxx | 5 + src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 83 +++++++- src/MEDCoupling_Swig/MEDCouplingCommon.i | 87 +++++++- 8 files changed, 414 insertions(+), 6 deletions(-) diff --git a/src/MEDCoupling/MEDCouplingCMesh.cxx b/src/MEDCoupling/MEDCouplingCMesh.cxx index 0895a17cf..6fdb51e6f 100644 --- a/src/MEDCoupling/MEDCouplingCMesh.cxx +++ b/src/MEDCoupling/MEDCouplingCMesh.cxx @@ -325,6 +325,31 @@ void MEDCouplingCMesh::getNodeGridStructure(int *res) const res[i]=getCoordsAt(i)->getNbOfElems(); } +std::vector MEDCouplingCMesh::getNodeGridStructure() const throw(INTERP_KERNEL::Exception) +{ + std::vector ret(getMeshDimension()); + getNodeGridStructure(&ret[0]); + return ret; +} + +MEDCouplingStructuredMesh *MEDCouplingCMesh::buildStructuredSubPart(const std::vector< std::pair >& cellPart) const throw(INTERP_KERNEL::Exception) +{ + checkCoherency(); + int dim(getMeshDimension()); + if(dim!=(int)cellPart.size()) + { + std::ostringstream oss; oss << "MEDCouplingCMesh::buildStructuredSubPart : the mesh dimension is " << dim << " and cell part size is " << cellPart.size() << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDCouplingAutoRefCountObjectPtr ret(dynamic_cast(deepCpy())); + for(int i=0;i tmp(ret->getCoordsAt(i)->selectByTupleId2(cellPart[i].first,cellPart[i].second+1,1)); + ret->setCoordsAt(i,tmp); + } + return ret.retn(); +} + int MEDCouplingCMesh::getSpaceDimension() const { int ret=0; diff --git a/src/MEDCoupling/MEDCouplingCMesh.hxx b/src/MEDCoupling/MEDCouplingCMesh.hxx index ef768835a..a6f8a182e 100644 --- a/src/MEDCoupling/MEDCouplingCMesh.hxx +++ b/src/MEDCoupling/MEDCouplingCMesh.hxx @@ -79,6 +79,8 @@ namespace ParaMEDMEM void getSplitCellValues(int *res) const; void getSplitNodeValues(int *res) const; void getNodeGridStructure(int *res) const; + std::vector getNodeGridStructure() const throw(INTERP_KERNEL::Exception); + MEDCouplingStructuredMesh *buildStructuredSubPart(const std::vector< std::pair >& cellPart) const throw(INTERP_KERNEL::Exception); //serialisation-unserialization void getTinySerializationInformation(std::vector& tinyInfoD, std::vector& tinyInfo, std::vector& littleStrings) const; void resizeForUnserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector& littleStrings) const; diff --git a/src/MEDCoupling/MEDCouplingCurveLinearMesh.cxx b/src/MEDCoupling/MEDCouplingCurveLinearMesh.cxx index 6e93efb12..11e84570a 100644 --- a/src/MEDCoupling/MEDCouplingCurveLinearMesh.cxx +++ b/src/MEDCoupling/MEDCouplingCurveLinearMesh.cxx @@ -341,6 +341,37 @@ std::vector MEDCouplingCurveLinearMesh::getNodeGridStructure() const throw( return _structure; } +MEDCouplingStructuredMesh *MEDCouplingCurveLinearMesh::buildStructuredSubPart(const std::vector< std::pair >& cellPart) const throw(INTERP_KERNEL::Exception) +{ + checkCoherency(); + int dim(getMeshDimension()); + std::vector dims(getMeshDimension()); + if(dim!=(int)cellPart.size()) + { + std::ostringstream oss; oss << "MEDCouplingCurveLinearMesh::buildStructuredSubPart : the mesh dimension is " << dim << " and cell part size is " << cellPart.size() << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + std::vector< std::pair > nodePartFormat(cellPart); + for(std::vector< std::pair >::iterator it=nodePartFormat.begin();it!=nodePartFormat.end();it++) + (*it).second++; + MEDCouplingAutoRefCountObjectPtr tmp1(BuildExplicitIdsFrom(getNodeGridStructure(),nodePartFormat)); + MEDCouplingAutoRefCountObjectPtr ret(dynamic_cast(deepCpy())); + const DataArrayDouble *coo(ret->getCoords()); + if(coo) + { + MEDCouplingAutoRefCountObjectPtr coo2(coo->selectByTupleIdSafe(tmp1->begin(),tmp1->end())); + ret->setCoords(coo2); + } + for(int i=0;isetNodeGridStructure(&dims[0],&dims[0]+dims.size()); + return ret.retn(); +} + void MEDCouplingCurveLinearMesh::getBoundingBox(double *bbox) const { if(!((const DataArrayDouble *)_coords)) diff --git a/src/MEDCoupling/MEDCouplingCurveLinearMesh.hxx b/src/MEDCoupling/MEDCouplingCurveLinearMesh.hxx index 047bac5ce..c165d1fb0 100644 --- a/src/MEDCoupling/MEDCouplingCurveLinearMesh.hxx +++ b/src/MEDCoupling/MEDCouplingCurveLinearMesh.hxx @@ -62,6 +62,7 @@ namespace ParaMEDMEM void setCoords(const DataArrayDouble *coords) throw(INTERP_KERNEL::Exception); void setNodeGridStructure(const int *gridStructBg, const int *gridStructEnd) throw(INTERP_KERNEL::Exception); std::vector getNodeGridStructure() const throw(INTERP_KERNEL::Exception); + MEDCouplingStructuredMesh *buildStructuredSubPart(const std::vector< std::pair >& cellPart) const throw(INTERP_KERNEL::Exception); // tools void getBoundingBox(double *bbox) const; MEDCouplingFieldDouble *getMeasureField(bool isAbs) const; diff --git a/src/MEDCoupling/MEDCouplingStructuredMesh.cxx b/src/MEDCoupling/MEDCouplingStructuredMesh.cxx index ed497f7a6..7878d83b6 100644 --- a/src/MEDCoupling/MEDCouplingStructuredMesh.cxx +++ b/src/MEDCoupling/MEDCouplingStructuredMesh.cxx @@ -303,10 +303,29 @@ MEDCouplingMesh *MEDCouplingStructuredMesh::buildPart(const int *start, const in MEDCouplingMesh *MEDCouplingStructuredMesh::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const { - MEDCouplingUMesh *um=buildUnstructured(); - MEDCouplingMesh *ret=um->buildPartAndReduceNodes(start,end,arr); - um->decrRef(); - return ret; + std::vector cgs(getCellGridStructure()); + std::vector< std::pair > cellPartFormat,nodePartFormat; + if(IsPartStructured(start,end,cgs,cellPartFormat)) + { + MEDCouplingAutoRefCountObjectPtr ret(buildStructuredSubPart(cellPartFormat)); + nodePartFormat=cellPartFormat; + for(std::vector< std::pair >::iterator it=nodePartFormat.begin();it!=nodePartFormat.end();it++) + (*it).second++; + MEDCouplingAutoRefCountObjectPtr tmp1(BuildExplicitIdsFrom(getNodeGridStructure(),nodePartFormat)); + MEDCouplingAutoRefCountObjectPtr tmp2(DataArrayInt::New()); tmp2->alloc(getNumberOfNodes(),1); + tmp2->fillWithValue(-1); + MEDCouplingAutoRefCountObjectPtr tmp3(DataArrayInt::New()); tmp3->alloc(tmp1->getNumberOfTuples(),1); tmp3->iota(0); + tmp2->setPartOfValues3(tmp3,tmp1->begin(),tmp1->end(),0,1,1); + arr=tmp2.retn(); + return ret.retn(); + } + else + { + MEDCouplingUMesh *um=buildUnstructured(); + MEDCouplingMesh *ret=um->buildPartAndReduceNodes(start,end,arr); + um->decrRef(); + return ret; + } } DataArrayInt *MEDCouplingStructuredMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception) @@ -473,3 +492,162 @@ void MEDCouplingStructuredMesh::GetPosFromId(int nodeId, int meshDim, const int res[i]=pos; } } + +std::vector MEDCouplingStructuredMesh::getCellGridStructure() const throw(INTERP_KERNEL::Exception) +{ + std::vector ret(getNodeGridStructure()); + std::transform(ret.begin(),ret.end(),ret.begin(),std::bind2nd(std::plus(),-1)); + return ret; +} + +/*! + * This method states if given part ids [ \a startIds, \a stopIds) and a structure \a st returns if it can be considered as a structured dataset. + * If true is returned \a partCompactFormat will contain the information to build the corresponding part. + * + * \sa MEDCouplingStructuredMesh::BuildExplicitIdsFrom + */ +bool MEDCouplingStructuredMesh::IsPartStructured(const int *startIds, const int *stopIds, const std::vector& st, std::vector< std::pair >& partCompactFormat) throw(INTERP_KERNEL::Exception) +{ + int dim((int)st.size()); + partCompactFormat.resize(dim); + if(dim<1 || dim>3) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::isPartStructured : input structure must be of dimension in [1,2,3] !"); + std::vector tmp2(dim),tmp(dim),tmp3(dim),tmp4(dim); tmp2[0]=1; + for(int i=1;i=st[dim-1]) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::IsPartStructured : first id in input is not in valid range !"); + if(sz==1) + { + for(int i=0;i=st[i]) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::IsPartStructured : last id in input is not in valid range !"); + partCompactFormat[i].second=tmp3[i]+1; + tmp4[i]=partCompactFormat[i].second-partCompactFormat[i].first; + if(tmp4[i]<=0) + return false; + } + const int *w(startIds); + switch(dim) + { + case 3: + { + for(int i=0;i& st, const std::vector< std::pair >& partCompactFormat) throw(INTERP_KERNEL::Exception) +{ + if(st.size()!=partCompactFormat.size()) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : input arrays must have the same size !"); + int nbOfItems(1); + std::vector dims(st.size()); + for(std::size_t i=0;ist[i]) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : invalid input range 1 !"); + if(partCompactFormat[i].second<0 || partCompactFormat[i].second>st[i]) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : invalid input range 2 !"); + if(partCompactFormat[i].second<=partCompactFormat[i].first) + throw INTERP_KERNEL::Exception("MEDCouplingStructuredMesh::BuildExplicitIdsFrom : invalid input range 3 !"); + dims[i]=partCompactFormat[i].second-partCompactFormat[i].first; + nbOfItems*=dims[i]; + } + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); + ret->alloc(nbOfItems,1); + int *pt(ret->getPointer()); + switch(st.size()) + { + case 3: + { + for(int i=0;i getNodeGridStructure() const throw(INTERP_KERNEL::Exception) = 0; + std::vector getCellGridStructure() const throw(INTERP_KERNEL::Exception); + virtual MEDCouplingStructuredMesh *buildStructuredSubPart(const std::vector< std::pair >& cellPart) const throw(INTERP_KERNEL::Exception) = 0; + static bool IsPartStructured(const int *startIds, const int *stopIds, const std::vector& st, std::vector< std::pair >& partCompactFormat) throw(INTERP_KERNEL::Exception); + static DataArrayInt *BuildExplicitIdsFrom(const std::vector& st, const std::vector< std::pair >& partCompactFormat) throw(INTERP_KERNEL::Exception); protected: MEDCouplingStructuredMesh(); MEDCouplingStructuredMesh(const MEDCouplingStructuredMesh& other, bool deepCpy); diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index b727ddeb5..7bd55b9a2 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -1867,7 +1867,7 @@ class MEDCouplingBasicsTest(unittest.TestCase): cells2=[25, 26] partMesh2, arr1=mesh1.buildPartAndReduceNodes(cells2) - self.assertTrue(isinstance(partMesh2,MEDCouplingUMesh)) + self.assertTrue(isinstance(partMesh2,MEDCouplingCMesh)) self.assertEqual(2,partMesh2.getNumberOfCellsWithType(NORM_HEXA8)); self.assertEqual(12,partMesh2.getNumberOfNodes()); @@ -13390,6 +13390,87 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertRaises(InterpKernelException,d.checkAllocated) pass + def testSwig2IsPartStructured1(self): + #dim 1 + d10=DataArrayInt([2,3,4,5,6,7,8,9,10,11]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d10,[13]) + self.assertTrue(a) ; self.assertEqual(b,[(2,12)]) + d11=DataArrayInt([2,3,4,5,6,7,8,10,9,11]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d11,[13]) + self.assertTrue(not a) + self.assertRaises(InterpKernelException,MEDCouplingStructuredMesh.IsPartStructured,d10,[11]) + #dim 2 + st=[10,4] + d20=DataArrayInt([1,2,3,4,11,12,13,14,21,22,23,24]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d20,st) + self.assertTrue(a) ; self.assertEqual(b,[(1,5),(0,3)]) + d20=DataArrayInt([1,2,3,4,12,11,13,14,21,22,23,24]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d20,st) + self.assertTrue(not a) + d20=DataArrayInt([1,2,3,4,11,12,13,15,21,22,23,24]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d20,st) + self.assertTrue(not a) + d21=DataArrayInt([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d21,st) + self.assertTrue(a) ; self.assertEqual(b,[(0,10),(0,4)]) + d22=DataArrayInt([1,2,3,4,11,12,13,14,21,22,23,24,31,32,33,34,41,42,43,44]) + self.assertRaises(InterpKernelException,MEDCouplingStructuredMesh.IsPartStructured,d22,st) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d22,[10,5]) + self.assertTrue(a) ; self.assertEqual(b,[(1,5),(0,5)]) + #dim 3 + d30=DataArrayInt([11,12,13,14,21,22,23,24,51,52,53,54,61,62,63,64]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d30,[10,4,2]) + self.assertTrue(a) ; self.assertEqual(b,[(1,5),(1,3),(0,2)]) + d31=DataArrayInt([11,12,13,14,21,22,24,23,51,52,53,54,61,62,63,64]) + a,b=MEDCouplingStructuredMesh.IsPartStructured(d31,[10,4,2]) + self.assertTrue(not a) + self.assertRaises(InterpKernelException,MEDCouplingStructuredMesh.IsPartStructured,d30,[10,4,1]) + pass + + def testSwig2PartStructured1(self): + c=MEDCouplingCMesh() ; c.setName("toto") + arr0=DataArrayDouble(10); arr0.iota() + arr1=DataArrayDouble(4) ; arr1.iota(3) + c.setCoords(arr0,arr1) + self.assertEqual(c.getNodeGridStructure(),(10,4)) + self.assertEqual(c.getCellGridStructure(),(9,3)) + d20=DataArrayInt([1,2,3,4,10,11,12,13,19,20,21,22]) + self.assertEqual(27,c.getNumberOfCells()) + self.assertEqual(40,c.getNumberOfNodes()) + self.assertEqual(2,c.getMeshDimension()) + c.checkCoherency() + # + arr2=MEDCouplingStructuredMesh.BuildExplicitIdsFrom([9,3],[(1,5),(0,3)]) + self.assertTrue(arr2.isEqual(DataArrayInt([1,2,3,4,10,11,12,13,19,20,21,22]))) + # CMesh + c2=c.buildStructuredSubPart([(1,5),(0,3)]) + c2.checkCoherency() + self.assertTrue(isinstance(c2,MEDCouplingCMesh)) + self.assertEqual(12,c2.getNumberOfCells()) + self.assertEqual(20,c2.getNumberOfNodes()) + self.assertEqual(2,c2.getMeshDimension()) + self.assertEqual("toto",c2.getName()) + self.assertTrue(c2.getCoordsAt(0).isEqual(DataArrayDouble([1.,2.,3.,4.,5.]),1e-12)) + self.assertTrue(c2.getCoordsAt(1).isEqual(DataArrayDouble([3.,4.,5.,6.]),1e-12)) + # + a,b=c.buildPartAndReduceNodes(d20) + a.checkCoherency() + exp2=DataArrayInt([-1,0,1,2,3,4,-1,-1,-1,-1,-1,5,6,7,8,9,-1,-1,-1,-1,-1,10,11,12,13,14,-1,-1,-1,-1,-1,15,16,17,18,19,-1,-1,-1,-1]) + self.assertTrue(exp2.isEqual(b)) + self.assertTrue(isinstance(a,MEDCouplingCMesh)) + self.assertTrue(a.buildUnstructured().isEqual(c.buildUnstructured().buildPartAndReduceNodes(d20)[0],1e-12)) + # CurveLinearMesh + c2=MEDCouplingCurveLinearMesh() ; c2.setName("toto") + c2.setCoords(c.buildUnstructured().getCoords()) + c2.setNodeGridStructure([10,4]) + c2.checkCoherency() + a,b=c2.buildPartAndReduceNodes(d20) + a.checkCoherency() + self.assertTrue(exp2.isEqual(b)) + self.assertTrue(isinstance(a,MEDCouplingCurveLinearMesh)) + self.assertTrue(a.buildUnstructured().isEqual(c2.buildUnstructured().buildPartAndReduceNodes(d20)[0],1e-12)) + pass + def setUp(self): pass pass diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index dad36a1bb..8cf917b1b 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -457,6 +457,8 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::MEDCoupling1DGTUMesh::Merge1DGTUMeshesOnSameCoords; %newobject ParaMEDMEM::MEDCouplingExtrudedMesh::New; %newobject ParaMEDMEM::MEDCouplingExtrudedMesh::build3DUnstructuredMesh; +%newobject ParaMEDMEM::MEDCouplingStructuredMesh::buildStructuredSubPart; +%newobject ParaMEDMEM::MEDCouplingStructuredMesh::BuildExplicitIdsFrom; %newobject ParaMEDMEM::MEDCouplingCMesh::New; %newobject ParaMEDMEM::MEDCouplingCMesh::clone; %newobject ParaMEDMEM::MEDCouplingCMesh::getCoordsAt; @@ -2930,7 +2932,91 @@ namespace ParaMEDMEM public: int getCellIdFromPos(int i, int j, int k) const throw(INTERP_KERNEL::Exception); int getNodeIdFromPos(int i, int j, int k) const throw(INTERP_KERNEL::Exception); + virtual std::vector getNodeGridStructure() const throw(INTERP_KERNEL::Exception); + std::vector getCellGridStructure() const throw(INTERP_KERNEL::Exception); static INTERP_KERNEL::NormalizedCellType GetGeoTypeGivenMeshDimension(int meshDim) throw(INTERP_KERNEL::Exception); + %extend + { + virtual MEDCouplingStructuredMesh *buildStructuredSubPart(PyObject *cellPart) const throw(INTERP_KERNEL::Exception) + { + int tmpp1=-1,tmpp2=-1; + std::vector tmp=fillArrayWithPyListInt2(cellPart,tmpp1,tmpp2); + std::vector< std::pair > inp; + if(tmpp2==2) + { + inp.resize(tmpp1); + for(int i=0;ibuildStructuredSubPart(inp); + } + + static DataArrayInt *BuildExplicitIdsFrom(PyObject *st, PyObject *part) throw(INTERP_KERNEL::Exception) + { + int tmpp1=-1,tmpp2=-1; + std::vector tmp=fillArrayWithPyListInt2(part,tmpp1,tmpp2); + std::vector< std::pair > inp; + if(tmpp2==2) + { + inp.resize(tmpp1); + for(int i=0;i stdvecTyyppArr; + const int *tmp4=convertObjToPossibleCpp1_Safe(st,sw,szArr,iTypppArr,stdvecTyyppArr); + std::vector tmp5(tmp4,tmp4+szArr); + // + return MEDCouplingStructuredMesh::BuildExplicitIdsFrom(tmp5,inp); + } + + static PyObject *IsPartStructured(PyObject *li, PyObject *st) throw(INTERP_KERNEL::Exception) + { + int szArr,sw,iTypppArr; + std::vector stdvecTyyppArr; + const int *tmp=convertObjToPossibleCpp1_Safe(li,sw,szArr,iTypppArr,stdvecTyyppArr); + int szArr2,sw2,iTypppArr2; + std::vector stdvecTyyppArr2; + const int *tmp2=convertObjToPossibleCpp1_Safe(st,sw2,szArr2,iTypppArr2,stdvecTyyppArr2); + std::vector tmp3(tmp2,tmp2+szArr2); + std::vector< std::pair > partCompactFormat; + bool ret0=MEDCouplingStructuredMesh::IsPartStructured(tmp,tmp+szArr,tmp3,partCompactFormat); + PyObject *ret=PyTuple_New(2); + PyObject *ret0Py=ret0?Py_True:Py_False; Py_XINCREF(ret0Py); + PyTuple_SetItem(ret,0,ret0Py); + PyObject *ret1Py=PyList_New(partCompactFormat.size()); + for(std::size_t i=0;i getNodeGridStructure() const throw(INTERP_KERNEL::Exception); %extend { MEDCouplingCurveLinearMesh() { -- 2.39.2