From: ageay Date: Mon, 5 Jul 2010 13:22:26 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: V5_1_main_FINAL~101 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=37f692bf2370d784f6716c9b0bcc42f26d1da3b6;p=tools%2Fmedcoupling.git *** empty log message *** --- diff --git a/src/MEDCoupling/MEDCouplingMemArray.cxx b/src/MEDCoupling/MEDCouplingMemArray.cxx index 3456e329b..96ca8a98e 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.cxx +++ b/src/MEDCoupling/MEDCouplingMemArray.cxx @@ -19,6 +19,7 @@ #include "MEDCouplingMemArray.txx" +#include #include using namespace ParaMEDMEM; @@ -88,6 +89,18 @@ void DataArrayDouble::reAlloc(int nbOfTuples) declareAsNew(); } +DataArrayInt *DataArrayDouble::convertToIntArr() const +{ + DataArrayInt *ret=DataArrayInt::New(); + ret->alloc(getNumberOfTuples(),getNumberOfComponents()); + int nbOfVals=getNbOfElems(); + const double *src=getConstPointer(); + int *dest=ret->getPointer(); + std::copy(src,src+nbOfVals,dest); + ret->copyStringInfoFrom(*this); + return ret; +} + void DataArrayDouble::setArrayIn(DataArrayDouble *newArray, DataArrayDouble* &arrayToSet) { if(newArray!=arrayToSet) @@ -334,6 +347,18 @@ void DataArrayInt::useArray(const int *array, bool ownership, DeallocType type, declareAsNew(); } +DataArrayDouble *DataArrayInt::convertToDblArr() const +{ + DataArrayDouble *ret=DataArrayDouble::New(); + ret->alloc(getNumberOfTuples(),getNumberOfComponents()); + int nbOfVals=getNbOfElems(); + const int *src=getConstPointer(); + double *dest=ret->getPointer(); + std::copy(src,src+nbOfVals,dest); + ret->copyStringInfoFrom(*this); + return ret; +} + void DataArrayInt::reAlloc(int nbOfTuples) { _mem.reAlloc(_info_on_compo.size()*nbOfTuples); @@ -368,6 +393,57 @@ DataArrayInt *DataArrayInt::aggregate(const DataArrayInt *a1, const DataArrayInt return ret; } +/*! + * This method create a minimal partition of groups 'groups' the std::iota array of size 'newNb'. + * This method returns an array of size 'newNb' that specifies for each item at which familyId it owns to, and this method returns + * for each group the familyId it contains. If an id so that id& groups, int newNb, std::vector< std::vector >& fidsOfGroups) +{ + DataArrayInt *ret=DataArrayInt::New(); + ret->alloc(newNb,1); + int *retPtr=ret->getPointer(); + std::fill(retPtr,retPtr+newNb,0); + int fid=1; + for(std::vector::const_iterator iter=groups.begin();iter!=groups.end();iter++) + { + const int *ptr=(*iter)->getConstPointer(); + int nbOfElem=(*iter)->getNbOfElems(); + int sfid=fid; + for(int j=0;j::const_iterator iter=groups.begin();iter!=groups.end();iter++,grId++) + { + std::set tmp; + const int *ptr=(*iter)->getConstPointer(); + int nbOfElem=(*iter)->getNbOfElems(); + for(const int *p=ptr;p!=ptr+nbOfElem;p++) + tmp.insert(retPtr[*p]); + fidsOfGroups[grId].insert(fidsOfGroups[grId].end(),tmp.begin(),tmp.end()); + } + return ret; +} + int *DataArrayInt::checkAndPreparePermutation(const int *start, const int *end) { int sz=std::distance(start,end); diff --git a/src/MEDCoupling/MEDCouplingMemArray.hxx b/src/MEDCoupling/MEDCouplingMemArray.hxx index 74d165bb9..d17fa018a 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.hxx +++ b/src/MEDCoupling/MEDCouplingMemArray.hxx @@ -101,6 +101,7 @@ namespace ParaMEDMEM namespace ParaMEDMEM { + class DataArrayInt; class DataArrayDouble : public DataArray { public: @@ -111,6 +112,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT bool isEqual(const DataArrayDouble& other, double prec) const; //!alloc or useArray should have been called before. MEDCOUPLING_EXPORT void reAlloc(int nbOfTuples); + MEDCOUPLING_EXPORT DataArrayInt *convertToIntArr() const; MEDCOUPLING_EXPORT void getTuple(int tupleId, double *res) const { std::copy(_mem.getConstPointerLoc(tupleId*_info_on_compo.size()),_mem.getConstPointerLoc((tupleId+1)*_info_on_compo.size()),res); } MEDCOUPLING_EXPORT double getIJ(int tupleId, int compoId) const { return _mem[tupleId*_info_on_compo.size()+compoId]; } MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, double newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; } @@ -147,6 +149,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT bool isEqual(const DataArrayInt& other) const; //!alloc or useArray should have been called before. MEDCOUPLING_EXPORT void reAlloc(int nbOfTuples); + MEDCOUPLING_EXPORT DataArrayDouble *convertToDblArr() const; MEDCOUPLING_EXPORT void getTuple(int tupleId, int *res) const { std::copy(_mem.getConstPointerLoc(tupleId*_info_on_compo.size()),_mem.getConstPointerLoc((tupleId+1)*_info_on_compo.size()),res); } MEDCOUPLING_EXPORT int getIJ(int tupleId, int compoId) const { return _mem[tupleId*_info_on_compo.size()+compoId]; } MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, int newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; } @@ -154,6 +157,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT static void setArrayIn(DataArrayInt *newArray, DataArrayInt* &arrayToSet); MEDCOUPLING_EXPORT const int *getConstPointer() const { return _mem.getConstPointer(); } MEDCOUPLING_EXPORT static DataArrayInt *aggregate(const DataArrayInt *a1, const DataArrayInt *a2, int offsetA2); + MEDCOUPLING_EXPORT static DataArrayInt *makePartition(const std::vector& groups, int newNb, std::vector< std::vector >& fidsOfGroups); MEDCOUPLING_EXPORT void useArray(const int *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo); MEDCOUPLING_EXPORT void writeOnPlace(int id, int element0, const int *others, int sizeOfOthers) { _mem.writeOnPlace(id,element0,others,sizeOfOthers); } //! nothing to do here because this class does not aggregate any TimeLabel instance. diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index 62e64ce7e..0207a8804 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -386,6 +386,7 @@ void MEDCouplingUMesh::convertToPolyTypes(const std::vector& cellIdsToConve int *newConnPtr=_nodal_connec->getPointer(); std::copy(connNew.begin(),connNew.end(),newConnPtr); } + computeTypes(); } /*! @@ -430,6 +431,153 @@ DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() return ret; } +/*! + * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy. + * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method. + */ +bool MEDCouplingUMesh::areCellsEquals(int cell1, int cell2, int compType) const +{ + switch(compType) + { + case 0: + return areCellsEquals0(cell1,cell2); + case 1: + return areCellsEquals1(cell1,cell2); + case 2: + return areCellsEquals2(cell1,cell2); + } + throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1 or 2."); +} + +bool MEDCouplingUMesh::areCellsEquals0(int cell1, int cell2) const +{ + const int *conn=getNodalConnectivity()->getConstPointer(); + const int *connI=getNodalConnectivityIndex()->getConstPointer(); + return std::equal(conn+connI[cell1],conn+connI[cell1+1],conn+connI[cell2]); +} + +bool MEDCouplingUMesh::areCellsEquals1(int cell1, int cell2) const +{ + throw INTERP_KERNEL::Exception("Policy comparison, not implemented yet !"); +} + +bool MEDCouplingUMesh::areCellsEquals2(int cell1, int cell2) const +{ + const int *conn=getNodalConnectivity()->getConstPointer(); + const int *connI=getNodalConnectivityIndex()->getConstPointer(); + std::set s1(conn+connI[cell1],conn+connI[cell1+1]); s1.erase(-1); + std::set s2(conn+connI[cell2],conn+connI[cell2+1]); s1.erase(-1); + return s1==s2; +} + +/*! + * This method find in candidate pool defined by ['candBg','candEnd') the cells equal following the polycy 'compType'. + * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned + * and result remains unchanged. + * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method. + * If in ['candBg','candEnd') pool -1 value is considered as an empty value. + * WARNING this method returns only ONE set of result ! + */ +bool MEDCouplingUMesh::areCellsEqualsInPool(const int *candBg, const int *candEnd, int compType, std::vector& result) const +{ + std::set cand(candBg,candEnd); + cand.erase(-1); + if(cand.size()<=1) + return false; + std::set::const_iterator end=cand.end(); end--; + bool ret=false; + for(std::set::const_iterator iter=cand.begin();iter!=end && !ret;iter++) + { + std::set::const_iterator begin2=iter; begin2++; + for(std::set::const_iterator iter2=begin2;iter2!=cand.end();iter2++) + { + if(areCellsEquals(*iter,*iter2,compType)) + { + if(!ret) + { + result.push_back(*iter); + ret=true; + } + result.push_back(*iter2); + } + } + } + return ret; +} + +/*! + * This method could potentially modify 'this'. This method merges cells if there are cells equal in 'this'. The comparison is specified by 'compType'. + * This method keeps the coordiantes of 'this'. + * + * @param compType input specifying the technique used to compare cells each other. + * 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy. + * 1 : permutation. cell1 and cell2 are equal if and the connectivity of cell2 can be deduced by those of cell1 by direct permutation and their type equal. + * 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. + * @return the correspondance array old to new. + */ +DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType) +{ + //std::vector bbox; + int nbOfCells=getNumberOfCells(); + //getBoundingBoxForBBTree(bbox); + //int spaceDim=getSpaceDimension(); + /*switch(spaceDim) + { + case 3: + BBTree<3,int> myTree(&bbox[0],0,0,nbOfCells,1e-12); + break; + case 2: + BBTree<2,int> myTree(&bbox[0],0,0,nbOfCells,1e-12); + break; + case 1: + BBTree<1,int> myTree(&bbox[0],0,0,nbOfCells,1e-12); + break; + default: + throw INTERP_KERNEL::Exception("Invalid spaceDimension : must be 1, 2 or 3."); + } + std::vector candidates; + myTree.getIntersectingElems(bb,candidates); + std::vector commonCells; + std::vector commonCellsI;*/ + DataArrayInt *revNodal=DataArrayInt::New(); + DataArrayInt *revNodalIndx=DataArrayInt::New(); + getReverseNodalConnectivity(revNodal,revNodalIndx); + int *revNodalPtr=revNodal->getPointer(); + int *revNodalIPtr=revNodalIndx->getPointer(); + std::vector commonCells; + std::vector commonCellsI; + commonCellsI.push_back(0); + int nbOfNodes=getNumberOfNodes(); + for(const int *pt=revNodalIPtr;pt!=revNodalIPtr+nbOfNodes;pt++) + { + std::vector common; + if(areCellsEqualsInPool(revNodalPtr+pt[0],revNodalPtr+pt[1],compType,common)) + { + commonCells.insert(commonCells.end(),common.begin(),common.end()); + commonCellsI.push_back(commonCellsI.back()+common.size()); + for(std::vector::const_iterator iter=common.begin();iter!=common.end();iter++) + { + for(int *w=revNodalPtr+pt[1];w!=revNodalPtr+revNodalIPtr[nbOfNodes];w++) + if(*w==(*iter)) + *w=-1; + } + } + } + revNodal->decrRef(); + revNodalIndx->decrRef(); + std::set vals; + for(int i=0;i::const_iterator end=commonCellsI.end(); end--; + for(std::vector::const_iterator iter=commonCellsI.begin();iter!=end;iter++) + for(std::vector::const_iterator iter2=commonCells.begin()+*iter+1;iter2!=commonCells.begin()+*(iter+1);iter2++) + vals.erase(*iter2);//commonCells.begin()+*iter+1,commonCells.begin()+*(iter+1)); + DataArrayInt *ret=DataArrayInt::New(); + ret->alloc(vals.size(),1); + std::copy(vals.begin(),vals.end(),ret->getPointer()); + return ret; +} + /*! * @param areNodesMerged if at least two nodes have been merged. * @return old to new node correspondance. @@ -1460,6 +1608,7 @@ DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const /*! * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'. + * The coords of 'mesh2' are added at the end of coords of 'mesh1'. */ MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) { @@ -1498,3 +1647,89 @@ MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshes(const MEDCouplingUMesh *mesh1, nodal->decrRef(); return ret; } + +/*! + * Idem mergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim. + * 'meshes' must be a non empty vector. 'meshes' have to be with the same mesh dimension. + */ +MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshesOnSameCoords(const std::vector& meshes) +{ + if(meshes.empty()) + throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty."); + DataArrayDouble *coords=meshes.front()->getCoords(); + int meshDim=meshes.front()->getMeshDimension(); + std::vector::const_iterator iter=meshes.begin(); + int meshLgth=0; + int meshIndexLgth=0; + for(;iter!=meshes.end();iter++) + { + if(coords!=(*iter)->getCoords()) + throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !"); + if(meshDim!=(*iter)->getMeshDimension()) + throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, fuseUMeshesOnSameCoords impossible !"); + meshLgth+=(*iter)->getMeshLength(); + meshIndexLgth+=(*iter)->getNumberOfCells(); + } + DataArrayInt *nodal=DataArrayInt::New(); + nodal->alloc(meshLgth,1); + int *nodalPtr=nodal->getPointer(); + DataArrayInt *nodalIndex=DataArrayInt::New(); + nodalIndex->alloc(meshIndexLgth+1,1); + int *nodalIndexPtr=nodalIndex->getPointer(); + int offset=0; + for(iter=meshes.begin();iter!=meshes.end();iter++) + { + const int *nod=(*iter)->getNodalConnectivity()->getConstPointer(); + const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer(); + int nbOfCells=(*iter)->getNumberOfCells(); + int meshLgth=(*iter)->getMeshLength(); + nodalPtr=std::copy(nod,nod+meshLgth,nodalPtr); + if(iter!=meshes.begin()) + nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus(),offset)); + else + nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr); + offset+=meshLgth; + } + MEDCouplingUMesh *ret=MEDCouplingUMesh::New(); + ret->setName("merge"); + ret->setMeshDimension(meshDim); + ret->setConnectivity(nodal,nodalIndex,true); + ret->setCoords(coords); + nodalIndex->decrRef(); + nodal->decrRef(); + return ret; +} + +/*! + * This method fuses meshes 'meshes' and returned the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh. + * If a same cell is detected in several meshes in 'meshes', this cell will appear only once in returned mesh (see ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for more details) + * + * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension. + * @param compType see MEDCouplingUMesh::zipConnectivityTraducer + * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh. + * The arrays contained in 'corr' parameter are returned with refcounter set to one. + * To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter. + * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with + * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension. + */ +MEDCouplingUMesh *MEDCouplingUMesh::fuseUMeshesOnSameCoords(const std::vector& meshes, int compType, std::vector& corr) +{ + //All checks are delegated to mergeUMeshesOnSameCoords + MEDCouplingUMesh *ret=mergeUMeshesOnSameCoords(meshes); + DataArrayInt *o2n=ret->zipConnectivityTraducer(compType); + corr.resize(meshes.size()); + int nbOfMeshes=meshes.size(); + int offset=0; + const int *o2nPtr=o2n->getConstPointer(); + for(int i=0;igetNumberOfCells(); + tmp->alloc(curNbOfCells,1); + std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer()); + offset+=curNbOfCells; + corr[i]=tmp; + } + o2n->decrRef(); + return ret; +} diff --git a/src/MEDCoupling/MEDCouplingUMesh.hxx b/src/MEDCoupling/MEDCouplingUMesh.hxx index 074de0b7b..f19cbebbc 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.hxx +++ b/src/MEDCoupling/MEDCouplingUMesh.hxx @@ -60,8 +60,13 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const; MEDCOUPLING_EXPORT void unserialization(const std::vector& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, const std::vector& littleStrings); //tools + MEDCOUPLING_EXPORT bool areCellsEquals(int cell1, int cell2, int compType) const; + MEDCOUPLING_EXPORT bool areCellsEquals0(int cell1, int cell2) const; + MEDCOUPLING_EXPORT bool areCellsEquals1(int cell1, int cell2) const; + MEDCOUPLING_EXPORT bool areCellsEquals2(int cell1, int cell2) const; MEDCOUPLING_EXPORT void convertToPolyTypes(const std::vector& cellIdsToConvert); MEDCOUPLING_EXPORT DataArrayInt *zipCoordsTraducer(); + MEDCOUPLING_EXPORT DataArrayInt *zipConnectivityTraducer(int compType); MEDCOUPLING_EXPORT void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const; MEDCOUPLING_EXPORT MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const; MEDCOUPLING_EXPORT DataArrayInt *mergeNodes(double precision, bool& areNodesMerged); @@ -84,10 +89,15 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, std::vector& elts, std::vector& eltsIndex) const; MEDCOUPLING_EXPORT void checkButterflyCells(std::vector& cells) const; MEDCOUPLING_EXPORT void getBoundingBoxForBBTree(std::vector& bbox) const; + //utilities for MED File RW MEDCOUPLING_EXPORT bool checkConsecutiveCellTypes() const; + MEDCOUPLING_EXPORT std::vector splitByType() const; + // MEDCOUPLING_EXPORT MEDCouplingMesh *mergeMyselfWith(const MEDCouplingMesh *other) const; MEDCOUPLING_EXPORT DataArrayDouble *getBarycenterAndOwner() const; MEDCOUPLING_EXPORT static MEDCouplingUMesh *mergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2); + MEDCOUPLING_EXPORT static MEDCouplingUMesh *mergeUMeshesOnSameCoords(const std::vector& meshes); + MEDCOUPLING_EXPORT static MEDCouplingUMesh *fuseUMeshesOnSameCoords(const std::vector& meshes, int compType, std::vector& corr); private: MEDCouplingUMesh(); MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy); @@ -95,6 +105,7 @@ namespace ParaMEDMEM void computeTypes(); void checkFullyDefined() const throw(INTERP_KERNEL::Exception); //tools + MEDCOUPLING_EXPORT bool areCellsEqualsInPool(const int *candBg, const int *candEnd, int compType, std::vector& result) const; MEDCouplingUMesh *buildPartOfMySelfKeepCoords(const int *start, const int *end) const; template void getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints, diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx index 14435a3c2..82ec32dd1 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx @@ -33,6 +33,7 @@ namespace ParaMEDMEM { CPPUNIT_TEST_SUITE(MEDCouplingBasicsTest); CPPUNIT_TEST( testArray ); + CPPUNIT_TEST( testArray2 ); CPPUNIT_TEST( testMesh ); CPPUNIT_TEST( testMeshPointsCloud ); CPPUNIT_TEST( testMeshM1D ); @@ -46,6 +47,7 @@ namespace ParaMEDMEM CPPUNIT_TEST( testBuildPartOfMySelf ); CPPUNIT_TEST( testBuildPartOfMySelfNode ); CPPUNIT_TEST( testZipCoords ); + //CPPUNIT_TEST( testZipConnectivity ); CPPUNIT_TEST( testEqualMesh ); CPPUNIT_TEST( testEqualFieldDouble ); CPPUNIT_TEST( testNatureChecking ); @@ -55,6 +57,7 @@ namespace ParaMEDMEM CPPUNIT_TEST( testFindCommonNodes ); CPPUNIT_TEST( testCheckButterflyCells ); CPPUNIT_TEST( testMergeMesh1 ); + CPPUNIT_TEST( testMergeMeshOnSameCoords1 ); CPPUNIT_TEST( testMergeField1 ); CPPUNIT_TEST( testFillFromAnalytic ); CPPUNIT_TEST( testFillFromAnalytic2 ); @@ -136,6 +139,7 @@ namespace ParaMEDMEM CPPUNIT_TEST_SUITE_END(); public: void testArray(); + void testArray2(); void testMesh(); void testMeshPointsCloud(); void testMeshM1D(); @@ -149,6 +153,7 @@ namespace ParaMEDMEM void testBuildPartOfMySelf(); void testBuildPartOfMySelfNode(); void testZipCoords(); + void testZipConnectivity(); void testEqualMesh(); void testEqualFieldDouble(); void testNatureChecking(); @@ -158,6 +163,7 @@ namespace ParaMEDMEM void testFindCommonNodes(); void testCheckButterflyCells(); void testMergeMesh1(); + void testMergeMeshOnSameCoords1(); void testMergeField1(); void testFillFromAnalytic(); void testFillFromAnalytic2(); diff --git a/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx b/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx index 0926cd44c..2ef3a31a6 100644 --- a/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx +++ b/src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx @@ -59,6 +59,25 @@ void MEDCouplingBasicsTest::testArray() } } +void MEDCouplingBasicsTest::testArray2() +{ + DataArrayDouble *arr=DataArrayDouble::New(); + arr->alloc(3,4); + double *tmp=arr->getPointer(); + const double arrRef[12]={12.,11.,10.,9.,8.,7.,6.,5.,4.,3.,2.,1.}; + std::copy(arrRef,arrRef+12,tmp); + arr->setInfoOnComponent(0,"ggg"); + arr->setInfoOnComponent(1,"hhhh"); + arr->setInfoOnComponent(2,"jj"); + arr->setInfoOnComponent(3,"kkkkkk"); + DataArrayInt *arr2=arr->convertToIntArr(); + DataArrayDouble *arr3=arr2->convertToDblArr(); + arr2->decrRef(); + CPPUNIT_ASSERT(arr->isEqual(*arr3,1e-14)); + arr3->decrRef(); + arr->decrRef(); +} + void MEDCouplingBasicsTest::testMesh() { const int nbOfCells=6; @@ -653,6 +672,39 @@ void MEDCouplingBasicsTest::testZipCoords() mesh->decrRef(); } +void MEDCouplingBasicsTest::testZipConnectivity() +{ + MEDCouplingUMesh *m1=build2DTargetMesh_1(); + MEDCouplingUMesh *m2=build2DTargetMesh_1(); + int cells1[3]={2,3,4}; + MEDCouplingPointSet *m3_1=m2->buildPartOfMySelf(cells1,cells1+3,true); + MEDCouplingUMesh *m3=dynamic_cast(m3_1); + CPPUNIT_ASSERT(m3); + m2->decrRef(); + MEDCouplingUMesh *m4=build2DSourceMesh_1(); + MEDCouplingUMesh *m5=MEDCouplingUMesh::mergeUMeshes(m1,m3); + m1->decrRef(); + m3->decrRef(); + MEDCouplingUMesh *m6=MEDCouplingUMesh::mergeUMeshes(m5,m4); + m4->decrRef(); + m5->decrRef(); + // + bool areNodesMerged; + CPPUNIT_ASSERT_EQUAL(10,m6->getNumberOfCells()); + CPPUNIT_ASSERT_EQUAL(22,m6->getNumberOfNodes()); + DataArrayInt *arr=m6->mergeNodes(1e-13,areNodesMerged); + arr->decrRef(); + CPPUNIT_ASSERT(areNodesMerged); + CPPUNIT_ASSERT_EQUAL(10,m6->getNumberOfCells()); + CPPUNIT_ASSERT_EQUAL(9,m6->getNumberOfNodes()); + // + arr=m6->zipConnectivityTraducer(0); + CPPUNIT_ASSERT_EQUAL(7,m6->getNumberOfCells()); + arr->decrRef(); + // + m6->decrRef(); +} + void MEDCouplingBasicsTest::testEqualMesh() { MEDCouplingUMesh *mesh1=build2DTargetMesh_1(); @@ -1090,6 +1142,43 @@ void MEDCouplingBasicsTest::testMergeMesh1() m2->decrRef(); } +void MEDCouplingBasicsTest::testMergeMeshOnSameCoords1() +{ + MEDCouplingUMesh *m1=build2DTargetMesh_1(); + MEDCouplingUMesh *m2=build2DTargetMesh_1(); + std::vector cells(5); + for(int i=0;i<5;i++) + cells[i]=i; + m2->convertToPolyTypes(cells); + m1->tryToShareSameCoords(*m2,1e-12); + MEDCouplingUMesh *m3=build2DTargetMesh_1(); + m3->tryToShareSameCoords(*m2,1e-12); + std::vector meshes; + meshes.push_back(m1); meshes.push_back(m2); meshes.push_back(m3); + MEDCouplingUMesh *m4=MEDCouplingUMesh::mergeUMeshesOnSameCoords(meshes); + m4->checkCoherency(); + CPPUNIT_ASSERT(m4->getCoords()==m1->getCoords()); + CPPUNIT_ASSERT_EQUAL(15,m4->getNumberOfCells()); + const int cells1[5]={0,1,2,3,4}; + MEDCouplingPointSet *m1_1=m4->buildPartOfMySelf(cells1,cells1+5,true); + m1_1->setName(m1->getName()); + CPPUNIT_ASSERT(m1->isEqual(m1_1,1e-12)); + const int cells2[5]={5,6,7,8,9}; + MEDCouplingPointSet *m2_1=m4->buildPartOfMySelf(cells2,cells2+5,true); + m2_1->setName(m2->getName()); + CPPUNIT_ASSERT(m2->isEqual(m2_1,1e-12)); + const int cells3[5]={10,11,12,13,14}; + MEDCouplingPointSet *m3_1=m4->buildPartOfMySelf(cells3,cells3+5,true); + m3_1->setName(m3->getName()); + CPPUNIT_ASSERT(m3->isEqual(m3_1,1e-12)); + m1_1->decrRef(); m2_1->decrRef(); m3_1->decrRef(); + // + m4->decrRef(); + m1->decrRef(); + m2->decrRef(); + m3->decrRef(); +} + void MEDCouplingBasicsTest::testMergeField1() { MEDCouplingUMesh *m1=build2DTargetMesh_1(); diff --git a/src/MEDCoupling_Swig/libMEDCoupling_Swig.i b/src/MEDCoupling_Swig/libMEDCoupling_Swig.i index 6ccbbb935..93d4cc45c 100644 --- a/src/MEDCoupling_Swig/libMEDCoupling_Swig.i +++ b/src/MEDCoupling_Swig/libMEDCoupling_Swig.i @@ -39,6 +39,8 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::DataArrayDouble::New; %newobject ParaMEDMEM::DataArrayInt::New; +%newobject ParaMEDMEM::DataArrayDouble::convertToIntArr; +%newobject ParaMEDMEM::DataArrayInt::convertToDblArr; %newobject ParaMEDMEM::MEDCouplingUMesh::New; %newobject ParaMEDMEM::MEDCouplingFieldDouble::New; %newobject ParaMEDMEM::MEDCouplingFieldDouble::mergeFields; diff --git a/src/MEDLoader/MEDLoader.cxx b/src/MEDLoader/MEDLoader.cxx index 51ea8bb8f..cd5c40ec9 100644 --- a/src/MEDLoader/MEDLoader.cxx +++ b/src/MEDLoader/MEDLoader.cxx @@ -159,6 +159,7 @@ namespace MEDLoaderNS void appendFieldDirectly(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f); void prepareCellFieldDoubleForWriting(const ParaMEDMEM::MEDCouplingFieldDouble *f, std::list& split); void writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh, bool forceFromScratch); + void writeUMeshesDirectly(const char *fileName, const char *meshName, const std::vector& meshes, bool forceFromScratch); void writeFieldAndMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f, bool forceFromScratch); } @@ -517,11 +518,11 @@ void MEDLoaderNS::readFieldDoubleDataInMedFile(const char *fileName, const char char maa_ass[MED_TAILLE_NOM+1]=""; med_float dt=0.0; med_booleen local; - med_int nbPdt=MEDnPasdetemps(fid,(char *)fieldName,MED_MAILLE,tabType[typeOfOutField][j]); + med_int nbPdt=MEDnPasdetemps(fid,(char *)fieldName,tabEnt[typeOfOutField],tabType[typeOfOutField][j]); bool found2=false; for(int k=0;k& meshes, bool forceFromScratch) +{ + med_idt fid=MEDouvrir((char *)fileName,forceFromScratch?MED_CREATION:MED_LECTURE_ECRITURE); + char maa[MED_TAILLE_NOM+1]; + strcpy(maa,meshName); + //MEDmaaCr(fid,maa,mesh->getSpaceDimension(),MED_NON_STRUCTURE,maa); + //MEDdimEspaceCr(fid,maa,mesh->getSpaceDimension()); + MEDfermer(fid); +} + void MEDLoaderNS::appendFieldDirectly(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f) { med_idt fid=MEDouvrir((char *)fileName,MED_LECTURE_ECRITURE); @@ -1254,7 +1268,10 @@ void MEDLoaderNS::appendFieldDirectly(const char *fileName, ParaMEDMEM::MEDCoupl case ParaMEDMEM::ON_NODES: { int nbOfTuples=f->getArray()->getNumberOfTuples(); - MEDchampEcr(fid,(char *)f->getMesh()->getName(),(char *)f->getName(),(unsigned char*)pt,MED_FULL_INTERLACE,nbOfTuples,(char *)MED_NOGAUSS, + char nommaa[MED_TAILLE_NOM+1]; + std::fill(nommaa,nommaa+MED_TAILLE_NOM,' '); nommaa[MED_TAILLE_NOM]='\0'; + strcpy(nommaa,f->getMesh()->getName()); + MEDchampEcr(fid,(char *)nommaa,(char *)f->getName(),(unsigned char*)pt,MED_FULL_INTERLACE,nbOfTuples,(char *)MED_NOGAUSS, MED_ALL,(char *)MED_NOPFL,MED_NO_PFLMOD,MED_NOEUD,MED_NONE,numdt,(char *)"",dt,numo); break; } @@ -1325,13 +1342,62 @@ void MEDLoader::WriteUMesh(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *m else { std::vector meshNames=GetMeshNames(fileName); - std::string fileNameCpp(mesh->getName()); - if(std::find(meshNames.begin(),meshNames.end(),fileNameCpp)==meshNames.end()) + if(std::find(meshNames.begin(),meshNames.end(),meshName)==meshNames.end()) MEDLoaderNS::writeUMeshDirectly(fileName,mesh,false); else { std::ostringstream oss; oss << "File \'" << fileName << "\' already exists and has already a mesh called \""; - oss << fileNameCpp << "\" !"; + oss << meshName << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } +} + +void MEDLoader::WriteUMeshes(const char *fileName, const char *meshNameC, const std::vector& meshes, bool writeFromScratch) +{ + std::string meshName(meshNameC); + if(meshName.empty()) + throw INTERP_KERNEL::Exception("Trying to write a unstructured mesh with no name ! MED file format needs a not empty mesh name : change 2nd parameter !"); + int status=MEDLoaderBase::getStatusOfFile(fileName); + if(status!=MEDLoaderBase::EXIST_RW && status!=MEDLoaderBase::NOT_EXIST) + { + std::ostringstream oss; oss << "File with name \'" << fileName << "\' has not valid permissions !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(meshes.empty()) + throw INTERP_KERNEL::Exception("List of meshes must be not empty !"); + DataArrayDouble *coords=meshes.front()->getCoords(); + for(std::vector::const_iterator iter=meshes.begin();iter!=meshes.end();iter++) + if(coords!=(*iter)->getCoords()) + throw INTERP_KERNEL::Exception("Meshes does not not share the same coordinates : try method MEDCouplingPointSet::tryToShareSameCoords !"); + std::set tmp; + for(std::vector::const_iterator iter=meshes.begin();iter!=meshes.end();iter++) + { + if(tmp.find((*iter)->getName())==tmp.end()) + tmp.insert((*iter)->getName()); + else + throw INTERP_KERNEL::Exception("The names of meshes must be different each other !"); + } + tmp.clear(); + if(writeFromScratch) + { + MEDLoaderNS::writeUMeshesDirectly(fileName,meshNameC,meshes,true); + return ; + } + if(status==MEDLoaderBase::NOT_EXIST) + { + MEDLoaderNS::writeUMeshesDirectly(fileName,meshNameC,meshes,true); + return; + } + else + { + std::vector meshNames=GetMeshNames(fileName); + if(std::find(meshNames.begin(),meshNames.end(),meshName)==meshNames.end()) + MEDLoaderNS::writeUMeshesDirectly(fileName,meshNameC,meshes,false); + else + { + std::ostringstream oss; oss << "File \'" << fileName << "\' already exists and has already a mesh called \""; + oss << meshName << "\" !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } } diff --git a/src/MEDLoader/MEDLoader.hxx b/src/MEDLoader/MEDLoader.hxx index cb2f74381..ffd68857c 100644 --- a/src/MEDLoader/MEDLoader.hxx +++ b/src/MEDLoader/MEDLoader.hxx @@ -89,6 +89,7 @@ public: static ParaMEDMEM::MEDCouplingFieldDouble *ReadFieldDoubleCell(const char *fileName, const char *meshName, int meshDimRelToMax, const char *fieldName, int iteration, int order); static ParaMEDMEM::MEDCouplingFieldDouble *ReadFieldDoubleNode(const char *fileName, const char *meshName, int meshDimRelToMax, const char *fieldName, int iteration, int order); static void WriteUMesh(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh, bool writeFromScratch); + static void WriteUMeshes(const char *fileName, const char *meshName, const std::vector& meshes, bool writeFromScratch); static void WriteField(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f, bool writeFromScratch); static void WriteFieldUsingAlreadyWrittenMesh(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f); private: diff --git a/src/MEDLoader/Test/MEDLoaderTest.cxx b/src/MEDLoader/Test/MEDLoaderTest.cxx index 27be8bb92..1784852e8 100644 --- a/src/MEDLoader/Test/MEDLoaderTest.cxx +++ b/src/MEDLoader/Test/MEDLoaderTest.cxx @@ -80,6 +80,116 @@ void MEDLoaderTest::testMesh3DRW() mesh->decrRef(); } +/*! + * Most basic test : one and only one MEDCoupling field in a new file. + */ +void MEDLoaderTest::testFieldRW1() +{ + MEDCouplingFieldDouble *f1=buildVecFieldOnCells_1(); + MEDLoader::WriteField("file6.med",f1,true); + MEDCouplingFieldDouble *f2=MEDLoader::ReadFieldDoubleCell("file6.med",f1->getMesh()->getName(),0,f1->getName(),0,1); + CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); + f1->decrRef(); + f2->decrRef(); + // + f1=buildVecFieldOnNodes_1(); + MEDLoader::WriteField("file7.med",f1,true); + f2=MEDLoader::ReadFieldDoubleNode("file7.med",f1->getMesh()->getName(),0,f1->getName(),2,3); + CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); + f1->decrRef(); + f2->decrRef(); +} + +/*! + * Multi field writing in a same file. + */ +void MEDLoaderTest::testFieldRW2() +{ + static const double VAL1=12345.67890314; + static const double VAL2=-1111111111111.; + MEDCouplingFieldDouble *f1=buildVecFieldOnCells_1(); + MEDLoader::WriteField("file8.med",f1,true); + f1->setTime(10.,8,9); + double *tmp=f1->getArray()->getPointer(); + tmp[0]=VAL1; + MEDLoader::WriteFieldUsingAlreadyWrittenMesh("file8.med",f1); + f1->setTime(10.14,18,19); + tmp[0]=VAL2; + MEDLoader::WriteFieldUsingAlreadyWrittenMesh("file8.med",f1); + //retrieving time steps... + MEDCouplingFieldDouble *f2=MEDLoader::ReadFieldDoubleCell("file8.med",f1->getMesh()->getName(),0,f1->getName(),8,9); + f1->setTime(10.,8,9); + tmp[0]=VAL1; + CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); + f2->decrRef(); + f2=MEDLoader::ReadFieldDoubleCell("file8.med",f1->getMesh()->getName(),0,f1->getName(),0,1); + MEDCouplingFieldDouble *f3=buildVecFieldOnCells_1(); + CPPUNIT_ASSERT(f3->isEqual(f2,1e-12,1e-12)); + f3->decrRef(); + f2->decrRef(); + f2=MEDLoader::ReadFieldDoubleCell("file8.med",f1->getMesh()->getName(),0,f1->getName(),18,19); + f1->setTime(10.14,18,19); + tmp[0]=VAL2; + CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); + f2->decrRef(); + f1->decrRef(); + //ON NODES + f1=buildVecFieldOnNodes_1(); + MEDLoader::WriteField("file9.med",f1,true); + f1->setTime(110.,108,109); + tmp=f1->getArray()->getPointer(); + tmp[3]=VAL1; + MEDLoader::WriteFieldUsingAlreadyWrittenMesh("file9.med",f1); + f1->setTime(210.,208,209); + tmp[3]=VAL2; + MEDLoader::WriteFieldUsingAlreadyWrittenMesh("file9.med",f1); + f2=MEDLoader::ReadFieldDoubleNode("file9.med",f1->getMesh()->getName(),0,f1->getName(),108,109); + f1->setTime(110.,108,109); + tmp[3]=VAL1; + CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); + f2->decrRef(); + f2=MEDLoader::ReadFieldDoubleNode("file9.med",f1->getMesh()->getName(),0,f1->getName(),2,3); + f3=buildVecFieldOnNodes_1(); + CPPUNIT_ASSERT(f3->isEqual(f2,1e-12,1e-12)); + f3->decrRef(); + f2->decrRef(); + f2=MEDLoader::ReadFieldDoubleNode("file9.med",f1->getMesh()->getName(),0,f1->getName(),208,209); + f1->setTime(210.,208,209); + tmp[3]=VAL2; + CPPUNIT_ASSERT(f1->isEqual(f2,1e-12,1e-12)); + f2->decrRef(); + f1->decrRef(); +} + +void MEDLoaderTest::testMultiMeshRW1() +{ + MEDCouplingUMesh *mesh1=build3DMesh_1(); + const int part1[5]={1,2,4,13,15}; + MEDCouplingUMesh *mesh2=(MEDCouplingUMesh *)mesh1->buildPartOfMySelf(part1,part1+5,true); + mesh2->setName("mesh2"); + const int part2[4]={3,4,13,14}; + MEDCouplingUMesh *mesh3=(MEDCouplingUMesh *)mesh1->buildPartOfMySelf(part2,part2+4,true); + mesh3->setName("mesh3"); + MEDCouplingUMesh *mesh4=MEDCouplingUMesh::New(); + mesh4->setName("mesh4"); + mesh4->setMeshDimension(3); + mesh4->allocateCells(1); + int conn[4]={0,11,1,3}; + mesh4->insertNextCell(INTERP_KERNEL::NORM_TETRA4,4,conn); + mesh4->finishInsertingCells(); + mesh4->setCoords(mesh1->getCoords()); + std::vector meshes; + meshes.push_back(mesh1); + meshes.push_back(mesh2); + meshes.push_back(mesh3); + meshes.push_back(mesh4); + MEDLoader::WriteUMeshes("file10.med","3DToto",meshes,true); + mesh4->decrRef(); + mesh3->decrRef(); + mesh2->decrRef(); + mesh1->decrRef(); +} + MEDCouplingUMesh *MEDLoaderTest::build1DMesh_1() { double coords[6]={ 0.0, 0.3, 0.75, 1.0, 1.4, 1.3 }; @@ -135,7 +245,7 @@ MEDCouplingUMesh *MEDLoaderTest::build2DMesh_1() targetMesh->insertNextCell(INTERP_KERNEL::NORM_TRI6,6,targetConn+6); targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+12); targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+16); - targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+20); + targetMesh->insertNextCell(INTERP_KERNEL::NORM_POLYGON,4,targetConn+20); targetMesh->finishInsertingCells(); DataArrayDouble *myCoords=DataArrayDouble::New(); myCoords->alloc(12,2); @@ -158,7 +268,7 @@ MEDCouplingUMesh *MEDLoaderTest::build3DSurfMesh_1() targetMesh->insertNextCell(INTERP_KERNEL::NORM_TRI6,6,targetConn+6); targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+12); targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+16); - targetMesh->insertNextCell(INTERP_KERNEL::NORM_QUAD4,4,targetConn+20); + targetMesh->insertNextCell(INTERP_KERNEL::NORM_POLYGON,4,targetConn+20); targetMesh->finishInsertingCells(); DataArrayDouble *myCoords=DataArrayDouble::New(); myCoords->alloc(12,3); @@ -233,3 +343,46 @@ MEDCouplingUMesh *MEDLoaderTest::build3DMesh_1() myCoords->decrRef(); return ret; } + +MEDCouplingFieldDouble *MEDLoaderTest::buildVecFieldOnCells_1() +{ + MEDCouplingUMesh *mesh=build3DSurfMesh_1(); + int nbOfCells=mesh->getNumberOfCells(); + MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME); + f1->setName("VectorFieldOnCells"); + f1->setMesh(mesh); + DataArrayDouble *array=DataArrayDouble::New(); + array->alloc(nbOfCells,3); + f1->setArray(array); + array->decrRef(); + double *tmp=array->getPointer(); + const double arr1[18]={0.,10.,20.,1.,11.,21.,2.,12.,22.,3.,13.,23.,4.,14.,24.,5.,15.,25.}; + std::copy(arr1,arr1+18,tmp); + f1->setTime(2.,0,1); + f1->checkCoherency(); + mesh->decrRef(); + return f1; +} + +MEDCouplingFieldDouble *MEDLoaderTest::buildVecFieldOnNodes_1() +{ + MEDCouplingUMesh *mesh=build3DSurfMesh_1(); + int nbOfNodes=mesh->getNumberOfNodes(); + MEDCouplingFieldDouble *f1=MEDCouplingFieldDouble::New(ON_NODES,ONE_TIME); + f1->setName("VectorFieldOnNodes"); + f1->setMesh(mesh); + DataArrayDouble *array=DataArrayDouble::New(); + array->alloc(nbOfNodes,3); + f1->setArray(array); + array->decrRef(); + double *tmp=array->getPointer(); + const double arr1[36]={ + 0.,10.,20.,1.,11.,21.,2.,12.,22.,3.,13.,23.,4.,14.,24.,5.,15.,25., + 1000.,10010.,10020.,1001.,10011.,10021.,1002.,10012.,10022.,1003.,10013.,10023.,1004.,10014.,10024.,1005.,10015.,10025., + }; + std::copy(arr1,arr1+36,tmp); + f1->setTime(2.12,2,3); + f1->checkCoherency(); + mesh->decrRef(); + return f1; +} diff --git a/src/MEDLoader/Test/MEDLoaderTest.hxx b/src/MEDLoader/Test/MEDLoaderTest.hxx index ae15fdb79..22350e413 100644 --- a/src/MEDLoader/Test/MEDLoaderTest.hxx +++ b/src/MEDLoader/Test/MEDLoaderTest.hxx @@ -25,6 +25,7 @@ namespace ParaMEDMEM { class MEDCouplingUMesh; + class MEDCouplingFieldDouble; class MEDLoaderTest : public CppUnit::TestFixture { @@ -34,6 +35,9 @@ namespace ParaMEDMEM CPPUNIT_TEST( testMesh2DRW ); CPPUNIT_TEST( testMesh3DSurfRW ); CPPUNIT_TEST( testMesh3DRW ); + CPPUNIT_TEST( testFieldRW1 ); + CPPUNIT_TEST( testFieldRW2 ); + CPPUNIT_TEST( testMultiMeshRW1 ); CPPUNIT_TEST_SUITE_END(); public: void testMesh1DRW(); @@ -41,12 +45,17 @@ namespace ParaMEDMEM void testMesh2DRW(); void testMesh3DSurfRW(); void testMesh3DRW(); + void testFieldRW1(); + void testFieldRW2(); + void testMultiMeshRW1(); private: MEDCouplingUMesh *build1DMesh_1(); MEDCouplingUMesh *build2DCurveMesh_1(); MEDCouplingUMesh *build2DMesh_1(); MEDCouplingUMesh *build3DSurfMesh_1(); MEDCouplingUMesh *build3DMesh_1(); + MEDCouplingFieldDouble *buildVecFieldOnCells_1(); + MEDCouplingFieldDouble *buildVecFieldOnNodes_1(); }; } diff --git a/src/ParaMEDMEM/DEC.cxx b/src/ParaMEDMEM/DEC.cxx index d8256bdc0..73a5577b7 100644 --- a/src/ParaMEDMEM/DEC.cxx +++ b/src/ParaMEDMEM/DEC.cxx @@ -24,9 +24,9 @@ #include "ParaFIELD.hxx" #include "ParaMESH.hxx" #include "DEC.hxx" -#include "ICoCoField.hxx" +#include "ICoCoField.h" #include "ICoCoMEDField.hxx" -#include "ICoCoTrioField.hxx" +#include "ICoCoTrioField.h" #include "MPIProcessorGroup.hxx" #include diff --git a/src/ParaMEDMEM/ICoCoField.cxx b/src/ParaMEDMEM/ICoCoField.cxx index 973376921..92c732a63 100644 --- a/src/ParaMEDMEM/ICoCoField.cxx +++ b/src/ParaMEDMEM/ICoCoField.cxx @@ -16,16 +16,12 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// ICoCo file common to several codes +// ICoCoField.cpp +// version 1.2 10/05/2010 -////////////////////////////////////////////////////////////////////////////// -// File: ICoCoField.cpp -// Directory: $TRIO_U_ROOT/Kernel/ICoCo -// Version: /main/1 -////////////////////////////////////////////////////////////////////////////// - -#include +#include #include -#include using namespace ICoCo; using std::string; diff --git a/src/ParaMEDMEM/ICoCoField.h b/src/ParaMEDMEM/ICoCoField.h new file mode 100644 index 000000000..b38eb0034 --- /dev/null +++ b/src/ParaMEDMEM/ICoCoField.h @@ -0,0 +1,24 @@ +// ICoCo file common to several codes +// ICoCoField.h +// version 1.2 10/05/2010 + +#ifndef _ICoCoField_included_ +#define _ICoCoField_included_ +#include + + +namespace ICoCo { + + class Field { + public: + Field(); + virtual ~Field(); + void setName(const std::string& name); + const std::string& getName() const; + const char* getCharName() const; + + private: + std::string* _name; + }; +} +#endif diff --git a/src/ParaMEDMEM/ICoCoField.hxx b/src/ParaMEDMEM/ICoCoField.hxx deleted file mode 100644 index c9d2813f6..000000000 --- a/src/ParaMEDMEM/ICoCoField.hxx +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2007-2010 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -#ifndef __ICOCOFIELD_HXX__ -#define __ICOCOFIELD_HXX__ - -#include - -namespace ICoCo -{ - class Field - { - public: - Field(); - virtual ~Field(); - void setName(const std::string& name); - const std::string& getName() const; - const char* getCharName() const; - - private: - std::string* _name; - }; -} - -#endif diff --git a/src/ParaMEDMEM/ICoCoMEDField.cxx b/src/ParaMEDMEM/ICoCoMEDField.cxx index cc3b61dd5..40a4a290b 100644 --- a/src/ParaMEDMEM/ICoCoMEDField.cxx +++ b/src/ParaMEDMEM/ICoCoMEDField.cxx @@ -18,7 +18,7 @@ // #include "ICoCoMEDField.hxx" -#include "ICoCoTrioField.hxx" +#include "ICoCoTrioField.h" #include "ProcessorGroup.hxx" #include "MEDCouplingUMesh.hxx" #include "MEDCouplingFieldDouble.hxx" diff --git a/src/ParaMEDMEM/ICoCoMEDField.hxx b/src/ParaMEDMEM/ICoCoMEDField.hxx index e43512ad3..63dbbeb4a 100644 --- a/src/ParaMEDMEM/ICoCoMEDField.hxx +++ b/src/ParaMEDMEM/ICoCoMEDField.hxx @@ -20,7 +20,7 @@ #ifndef __ICOCOMEDFIELD_HXX__ #define __ICOCOMEDFIELD_HXX__ -#include "ICoCoField.hxx" +#include "ICoCoField.h" #include "MEDCouplingUMesh.hxx" #include "MEDCouplingFieldDouble.hxx" diff --git a/src/ParaMEDMEM/ICoCoTrioField.cxx b/src/ParaMEDMEM/ICoCoTrioField.cxx index 1e5a14d22..173cd3323 100644 --- a/src/ParaMEDMEM/ICoCoTrioField.cxx +++ b/src/ParaMEDMEM/ICoCoTrioField.cxx @@ -16,28 +16,41 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// ICoCo file common to several codes +// ICoCoTrioField.cpp +// version 1.2 10/05/2010 -////////////////////////////////////////////////////////////////////////////// -// File: ICoCoTrioField.cpp -// Directory: $TRIO_U_ROOT/Kernel/Framework -// Version: -////////////////////////////////////////////////////////////////////////////// - -#include +#include #include #include -#include +#include using namespace ICoCo; using namespace std; +// Default constructor TrioField::TrioField() : _type(0), + _mesh_dim(0), + _space_dim(0), + _nbnodes(0), + _nodes_per_elem(0), + _nb_elems(0), + _itnumber(0), _connectivity(0), _coords(0), + _time1(0.), + _time2(0.), + _nb_field_components(0), _field(0), _has_field_ownership(false) { } +// Copy constructor +TrioField::TrioField(const TrioField& OtherField) { + (*this)=OtherField; +} + +// Destructor TrioField::~TrioField() { clear(); } @@ -57,134 +70,124 @@ void TrioField::clear() { _has_field_ownership=false; } -int TrioField::nb_values() const -{ +// Returns the number of value locations +// The size of field is nb_values()*_nb_field_components +int TrioField::nb_values() const { if (_type==0) return _nb_elems; - else - if (_type==1) - return _nbnodes; - exit(-1); + else if (_type==1) + return _nbnodes; + throw 0; + //exit(-1); return -1; - } + +// Save field to a .field file (loadable by visit!) void TrioField::save(ostream& os) const{ - os <> name; setName(name); - in>>_type; - in>>_mesh_dim; - in>> _space_dim; - in>> _nbnodes; - in>> _nodes_per_elem; - in>> _nb_elems; + in >> _type; + in >> _mesh_dim; + in >> _space_dim; + in >> _nbnodes; + in >> _nodes_per_elem; + in >> _nb_elems; - in>> _itnumber; + in >> _itnumber; if (_connectivity) delete [] _connectivity; _connectivity=new int[_nodes_per_elem*_nb_elems]; - for (int i=0;i<_nb_elems;i++) - { - for (int j=0;j<_nodes_per_elem;j++) - in>>_connectivity[i*_nodes_per_elem+j]; - - } + for (int i=0;i<_nb_elems;i++) { + for (int j=0;j<_nodes_per_elem;j++) + in >> _connectivity[i*_nodes_per_elem+j]; + } if (_coords) delete [] _coords; _coords=new double[_nbnodes*_space_dim]; - for (int i=0;i<_nbnodes;i++) - { - for (int j=0;j<_space_dim;j++) - in>> _coords[i*_space_dim+j] ; - - } + for (int i=0;i<_nbnodes;i++) { + for (int j=0;j<_space_dim;j++) + in >> _coords[i*_space_dim+j]; + } - in>> _time1; - in>>_time2; - in>> _nb_field_components; + in >> _time1; + in >> _time2; + in >> _nb_field_components; int test; - in>> test; - if (test) - { - if (_field) - delete [] _field; - _field=new double[_nb_field_components*nb_values()]; - for (int i=0;i> _field[i*_nb_field_components+j]; - - } + in >> test; + if (test) { + if (_field) + delete [] _field; + _field=new double[_nb_field_components*nb_values()]; + for (int i=0;i> _field[i*_nb_field_components+j]; } + } else - { - _field=0; - } - in>> _has_field_ownership; + _field=0; + + in >> _has_field_ownership; } - void TrioField::print() { - } // After the call to set_standalone(), field ownership is true and field is allocated -// to the size _nb_field_components*_nb_elems. +// to the size _nb_field_components*nb_values(). // The values of the field have been copied if necessary. void TrioField::set_standalone() { if (!_field) { - _field=new double[_nb_field_components*_nb_elems]; + _field=new double[_nb_field_components*nb_values()]; _has_field_ownership=true; } else if (!_has_field_ownership) { - double *tmp_field=new double[_nb_field_components*_nb_elems]; - memcpy(tmp_field,_field,_nb_field_components*_nb_elems*sizeof(double)); + double *tmp_field=new double[_nb_field_components*nb_values()]; + memcpy(tmp_field,_field,_nb_field_components*nb_values()*sizeof(double)); _field=tmp_field; _has_field_ownership=true; } @@ -192,6 +195,7 @@ void TrioField::set_standalone() { // Used to simulate a 0D geometry (Cathare/Trio for example). void TrioField::dummy_geom() { + _type=0; _mesh_dim=2; _space_dim=2; _nbnodes=3; @@ -201,9 +205,9 @@ void TrioField::dummy_geom() { if (_connectivity) delete[] _connectivity; _connectivity=new int[3]; - _connectivity[0]=1; - _connectivity[1]=2; - _connectivity[2]=3; + _connectivity[0]=0; + _connectivity[1]=1; + _connectivity[2]=2; if (_coords) delete[] _coords; _coords=new double[6]; @@ -213,53 +217,60 @@ void TrioField::dummy_geom() { _coords[3]=0; _coords[4]=0; _coords[5]=1; + _time1=0; + _time2=1; + _nb_field_components=1; if (_field && _has_field_ownership) delete[] _field; _has_field_ownership=false; _field=0; } -// Surcharge de l'operateur = pour la classe TrioField -// remplace les valeurs trouvee dans le TrioField donnee en parametre +// Overloading operator = for TrioField +// This becomes an exact copy of NewField. +// If NewField._has_field_ownership is false, they point to the same values. +// Otherwise the values are copied. TrioField& TrioField::operator=(const TrioField& NewField){ - clear(); - _type=NewField._type; - _mesh_dim=NewField._mesh_dim; - _space_dim=NewField._space_dim; - _nbnodes=NewField._nbnodes; - _nodes_per_elem=NewField._nodes_per_elem; - _nb_elems=NewField._nb_elems; - _itnumber=NewField._itnumber; - // std::string _name; // ?? Hérité de la classe mère - _time1=NewField._time1; - _time2=NewField._time2; - _nb_field_components=NewField._nb_field_components; + clear(); - if (!NewField._connectivity) - _connectivity=0; - else { - _connectivity=new int[_nodes_per_elem*_nb_elems]; - memcpy( _connectivity,NewField._connectivity,_nodes_per_elem*_nb_elems*sizeof(int)); - } + _type=NewField._type; + _mesh_dim=NewField._mesh_dim; + _space_dim=NewField._space_dim; + _nbnodes=NewField._nbnodes; + _nodes_per_elem=NewField._nodes_per_elem; + _nb_elems=NewField._nb_elems; + _itnumber=NewField._itnumber; + _time1=NewField._time1; + _time2=NewField._time2; + _nb_field_components=NewField._nb_field_components; - if (!NewField._coords) - _coords=0; - else { - _coords=new double[_nbnodes*_space_dim]; - memcpy( _coords,NewField._coords,_nbnodes*_space_dim*sizeof(double)); - } + if (!NewField._connectivity) + _connectivity=0; + else { + _connectivity=new int[_nodes_per_elem*_nb_elems]; + memcpy( _connectivity,NewField._connectivity,_nodes_per_elem*_nb_elems*sizeof(int)); + } - //Copie des valeurs du champ - _has_field_ownership=NewField._has_field_ownership; - if (_has_field_ownership) { - _field=new double[_nb_elems*_nb_field_components]; - memcpy(_field,NewField._field,_nb_elems*_nb_field_components*sizeof(double)); - } - else - _field=NewField._field; + if (!NewField._coords) + _coords=0; + else { + _coords=new double[_nbnodes*_space_dim]; + memcpy( _coords,NewField._coords,_nbnodes*_space_dim*sizeof(double)); + } - return(*this); + //Copie des valeurs du champ + _has_field_ownership=NewField._has_field_ownership; + if (_has_field_ownership) { + _field=new double[nb_values()*_nb_field_components]; + memcpy(_field,NewField._field,nb_values()*_nb_field_components*sizeof(double)); + } + else + _field=NewField._field; + + return(*this); } + + diff --git a/src/ParaMEDMEM/ICoCoTrioField.h b/src/ParaMEDMEM/ICoCoTrioField.h new file mode 100644 index 000000000..8d9f4703d --- /dev/null +++ b/src/ParaMEDMEM/ICoCoTrioField.h @@ -0,0 +1,73 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// ICoCo file common to several codes +// ICoCoTrioField.h +// version 1.2 10/05/2010 + +#ifndef _ICoCoTrioField_included_ +#define _ICoCoTrioField_included_ + +#include +namespace ICoCo { + + ////////////////////////////////////////////////////////////////////////////// + // + // .DESCRIPTION + // class TrioField, used for coupling Trio codes via the ICoCo interface + // This structure contains all the necessary information + // for constructing a ParaMEDMEM::ParaFIELD (with the addition of the MPI + // communicator). + // This structure can either own or not _field values (_has_field_ownership) + // For _coords, _connectivity and _field, a null pointer means no data allocated. + // _coords and _connectivity tables, when allocated, are always owned by the TrioField. + // + ////////////////////////////////////////////////////////////////////////////// + class TrioField:public Field { + public: + + TrioField(); + TrioField(const TrioField& OtherField); + ~TrioField(); + void clear(); + void set_standalone(); + void dummy_geom(); + TrioField& operator=(const TrioField& NewField); + void save(std::ostream& os) const; + void restore(std::istream& in); + int nb_values() const ; + + public: + int _type ; // 0 elem 1 nodes + int _mesh_dim; + int _space_dim; + int _nbnodes; + int _nodes_per_elem; + int _nb_elems; + int _itnumber; + int* _connectivity; + double* _coords; + + double _time1,_time2; + int _nb_field_components; + double* _field; + bool _has_field_ownership; + }; +} + +#endif diff --git a/src/ParaMEDMEM/ICoCoTrioField.hxx b/src/ParaMEDMEM/ICoCoTrioField.hxx deleted file mode 100644 index cb238ff5c..000000000 --- a/src/ParaMEDMEM/ICoCoTrioField.hxx +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (C) 2007-2010 CEA/DEN, EDF R&D -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -////////////////////////////////////////////////////////////////////////////// -// File: ICoCoTrioField.h -// Directory: $TRIO_U_ROOT/Kernel/Framework -// Version: -////////////////////////////////////////////////////////////////////////////// - -#ifndef _ICOCOTRIOFIELD_HXX_ -#define _ICOCOTRIOFIELD_HXX_ - -#include -namespace ICoCo -{ - /*! - \brief structure for coupling Trio codes via the ICoCo interface - - This structure contains all the necessary information - for constructing a ParaMEDMEM::ParaFIELD (with the addition of the MPI - communicator). The ICoCo API specifies two kinds of calls for - the ICoCo::Field : either with the mesh only or with the entire information (mesh and field). - This structure can therefore be left without _time, _nb_field_components, _field - information, which are related to the field values. - - _coords and _connectivity tables are always owned by the TrioField. - - */ - class TrioField:public Field - { - public: - - TrioField(); - ~TrioField(); - void clear(); - void print(); - void set_standalone(); - void dummy_geom(); - TrioField& operator=(const TrioField& NewField); - void save(std::ostream& os) const; - void restore(std::istream& in); - int nb_values() const ; - public: - int _type ; // 0 elem 1 nodes - int _mesh_dim; - int _space_dim; - int _nbnodes; - int _nodes_per_elem; - int _nb_elems; - int _itnumber; - int* _connectivity; - double* _coords; - - double _time1,_time2; - int _nb_field_components; - double* _field; - bool _has_field_ownership; - }; -} - -#endif diff --git a/src/ParaMEDMEM/Makefile.am b/src/ParaMEDMEM/Makefile.am index 5bc571a2b..8d68675a1 100644 --- a/src/ParaMEDMEM/Makefile.am +++ b/src/ParaMEDMEM/Makefile.am @@ -41,9 +41,9 @@ InterpKernelDEC.hxx\ ExplicitCoincidentDEC.hxx\ ElementLocator.hxx\ ExplicitMapping.hxx\ -ICoCoField.hxx \ +ICoCoField.h \ ICoCoMEDField.hxx \ -ICoCoTrioField.hxx \ +ICoCoTrioField.h \ MPIAccess.hxx \ MPIAccessDEC.hxx \ TimeInterpolator.hxx \ diff --git a/src/ParaMEDMEMTest/ParaMEDMEMTest_Gauthier1.cxx b/src/ParaMEDMEMTest/ParaMEDMEMTest_Gauthier1.cxx index 11c582843..31421641f 100644 --- a/src/ParaMEDMEMTest/ParaMEDMEMTest_Gauthier1.cxx +++ b/src/ParaMEDMEMTest/ParaMEDMEMTest_Gauthier1.cxx @@ -28,7 +28,7 @@ #include "InterpKernelDEC.hxx" #include #include -#include "ICoCoTrioField.hxx" +#include "ICoCoTrioField.h" #include #include #include diff --git a/src/ParaMEDMEMTest/ParaMEDMEMTest_ICocoTrio.cxx b/src/ParaMEDMEMTest/ParaMEDMEMTest_ICocoTrio.cxx index 386491362..e4137c0e7 100644 --- a/src/ParaMEDMEMTest/ParaMEDMEMTest_ICocoTrio.cxx +++ b/src/ParaMEDMEMTest/ParaMEDMEMTest_ICocoTrio.cxx @@ -26,7 +26,7 @@ #include "InterpKernelDEC.hxx" #include #include -#include "ICoCoTrioField.hxx" +#include "ICoCoTrioField.h" #include #include