From: Anthony Geay Date: Fri, 26 Sep 2014 13:08:35 +0000 (+0200) Subject: On the road of the ParaMEDReader. MEDLoader can load partially a MEDFileUMesh from... X-Git-Tag: V7_5_0a1~12 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=82f004f6ae89d0ca193c46343927ad1e87957f88;p=modules%2Fmed.git On the road of the ParaMEDReader. MEDLoader can load partially a MEDFileUMesh from MED file. --- diff --git a/src/MEDCoupling/MEDCoupling1GTUMesh.cxx b/src/MEDCoupling/MEDCoupling1GTUMesh.cxx index ec244e6c4..5c9b32456 100644 --- a/src/MEDCoupling/MEDCoupling1GTUMesh.cxx +++ b/src/MEDCoupling/MEDCoupling1GTUMesh.cxx @@ -1005,6 +1005,29 @@ struct MEDCouplingAccVisit /// @endcond +/*! + * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller. + * The returned node ids are sortes ascendingly. This method is closed to MEDCoupling1SGTUMesh::getNodeIdsInUse except + * the format of returned DataArrayInt instance. + * + * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids. + * \sa MEDCoupling1SGTUMesh::getNodeIdsInUse + */ +DataArrayInt *MEDCoupling1SGTUMesh::computeFetchedNodeIds() const +{ + checkCoherencyOfConnectivity(); + int nbNodes(getNumberOfNodes()); + std::vector fetchedNodes(nbNodes,false); + computeNodeIdsAlg(fetchedNodes); + int sz((int)std::count(fetchedNodes.begin(),fetchedNodes.end(),true)); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(sz,1); + int *retPtr(ret->getPointer()); + for(int i=0;i ret=DataArrayInt::New(); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1); int *traducer=ret->getPointer(); std::fill(traducer,traducer+nbOfNodes,-1); @@ -1043,6 +1067,33 @@ DataArrayInt *MEDCoupling1SGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const return ret.retn(); } +/*! + * 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) +{ + getNumberOfCells();//only to check that all is well defined. + int *begPtr(_conn->getPointer()); + int nbElt(_conn->getNumberOfTuples()); + int *endPtr(begPtr+nbElt); + for(int *it=begPtr;it!=endPtr;it++) + { + std::map::const_iterator it2(newNodeNumbersO2N.find(*it)); + if(it2!=newNodeNumbersO2N.end()) + { + *it=(*it2).second; + } + else + { + std::ostringstream oss; oss << "MEDCoupling1SGTUMesh::renumberNodesInConn : At pos #" << std::distance(begPtr,it) << " of nodal connectivity value is " << *it << ". Not in map !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + updateTime(); +} + /*! * Changes ids of nodes within the nodal connectivity arrays according to a permutation * array in "Old to New" mode. The node coordinates array is \b not changed by this method. @@ -1229,20 +1280,16 @@ MEDCouplingPointSet *MEDCoupling1SGTUMesh::buildPartOfMySelfKeepCoords2(int star void MEDCoupling1SGTUMesh::computeNodeIdsAlg(std::vector& nodeIdsInUse) const { int sz((int)nodeIdsInUse.size()); - int nbCells(getNumberOfCells()); - int nbOfNodesPerCell(getNumberOfNodesPerCell()); - const int *w(_conn->begin()); - for(int i=0;i=0 && *wbegin();conn!=_conn->end();conn++) + { + if(*conn>=0 && *connbegin(),conn) << " value is " << *conn << " must be in [0," << sz << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } } MEDCoupling1SGTUMesh *MEDCoupling1SGTUMesh::buildSetInstanceFromThis(int spaceDim) const @@ -2779,21 +2826,21 @@ MEDCouplingPointSet *MEDCoupling1DGTUMesh::buildPartOfMySelfKeepCoords2(int star void MEDCoupling1DGTUMesh::computeNodeIdsAlg(std::vector& nodeIdsInUse) const { + checkCoherency2(); int sz((int)nodeIdsInUse.size()); - int nbCells(getNumberOfCells()); - const int *w(_conn->begin()),*wi(_conn_indx->begin()); - for(int i=0;ibegin();conn!=_conn->end();conn++) + { + if(*conn>=0 && *conn=0 && *ptbegin(),conn) << " value is " << *conn << " must be in [0," << sz << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } } + } } void MEDCoupling1DGTUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const @@ -2972,6 +3019,35 @@ void MEDCoupling1DGTUMesh::unserialization(const std::vector& tinyInfoD, _conn_indx->finishUnserialization(tinyInfo4,littleStrings4); } +/*! + * Finds nodes not used in any cell and returns an array giving a new id to every node + * by excluding the unused nodes, for which the array holds -1. The result array is + * a mapping in "Old to New" mode. + * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity. + * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a + * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1 + * if the node is unused or a new id else. The caller is to delete this + * array using decrRef() as it is no more needed. + * \throw If the coordinates array is not set. + * \throw If the nodal connectivity of cells is not defined. + * \throw If the nodal connectivity includes an invalid id. + * \sa MEDCoupling1DGTUMesh::computeFetchedNodeIds + */ +DataArrayInt *MEDCoupling1DGTUMesh::computeFetchedNodeIds() const +{ + checkCoherency2(); + int nbNodes(getNumberOfNodes()); + std::vector fetchedNodes(nbNodes,false); + computeNodeIdsAlg(fetchedNodes); + int sz((int)std::count(fetchedNodes.begin(),fetchedNodes.end(),true)); + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(sz,1); + int *retPtr(ret->getPointer()); + for(int i=0;i& tinyInfoD, * \throw If the coordinates array is not set. * \throw If the nodal connectivity of cells is not defined. * \throw If the nodal connectivity includes an invalid id. + * \sa MEDCoupling1DGTUMesh::computeFetchedNodeIds */ DataArrayInt *MEDCoupling1DGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const { @@ -3016,6 +3093,41 @@ DataArrayInt *MEDCoupling1DGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const return ret.retn(); } +/*! + * 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 MEDCoupling1DGTUMesh::renumberNodesInConn(const std::map& newNodeNumbersO2N) +{ + getNumberOfCells();//only to check that all is well defined. + // + int nbElemsIn(getNumberOfNodes()),nbOfTuples(_conn->getNumberOfTuples()); + int *pt(_conn->getPointer()); + for(int i=0;i=0 && *pt::const_iterator it(newNodeNumbersO2N.find(*pt)); + if(it!=newNodeNumbersO2N.end()) + *pt=(*it).second; + else + { + std::ostringstream oss; oss << "MEDCoupling1DGTUMesh::renumberNodesInConn : At pos #" << i << " of connectivity, node id is " << *pt << ". Not in keys of input map !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + else + { + std::ostringstream oss; oss << "MEDCoupling1DGTUMesh::renumberNodesInConn : error on tuple #" << i << " value is " << *pt << " and indirectionnal array as a size equal to " << nbElemsIn; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + // + updateTime(); +} + /*! * Changes ids of nodes within the nodal connectivity arrays according to a permutation * array in "Old to New" mode. The node coordinates array is \b not changed by this method. @@ -3030,9 +3142,8 @@ void MEDCoupling1DGTUMesh::renumberNodesInConn(const int *newNodeNumbersO2N) { getNumberOfCells();//only to check that all is well defined. // - int nbElemsIn=getNumberOfNodes(); - int nbOfTuples=_conn->getNumberOfTuples(); - int *pt=_conn->getPointer(); + int nbElemsIn(getNumberOfNodes()),nbOfTuples(_conn->getNumberOfTuples()); + int *pt(_conn->getPointer()); for(int i=0;ideclareAsNew(); // updateTime(); } diff --git a/src/MEDCoupling/MEDCoupling1GTUMesh.hxx b/src/MEDCoupling/MEDCoupling1GTUMesh.hxx index 4637c1146..50169f5ab 100644 --- a/src/MEDCoupling/MEDCoupling1GTUMesh.hxx +++ b/src/MEDCoupling/MEDCoupling1GTUMesh.hxx @@ -128,7 +128,9 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const; MEDCOUPLING_EXPORT void checkFullyDefined() const; 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 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; @@ -218,7 +220,9 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const; MEDCOUPLING_EXPORT void checkFullyDefined() const; 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 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/MEDCouplingMemArray.hxx b/src/MEDCoupling/MEDCouplingMemArray.hxx index bfd822845..dedfb16d1 100644 --- a/src/MEDCoupling/MEDCouplingMemArray.hxx +++ b/src/MEDCoupling/MEDCouplingMemArray.hxx @@ -284,7 +284,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT double getIJSafe(int tupleId, int compoId) const; MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, double newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; declareAsNew(); } MEDCOUPLING_EXPORT void setIJSilent(int tupleId, int compoId, double newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; } - MEDCOUPLING_EXPORT double *getPointer() { return _mem.getPointer(); } + MEDCOUPLING_EXPORT double *getPointer() { return _mem.getPointer(); declareAsNew(); } MEDCOUPLING_EXPORT static void SetArrayIn(DataArrayDouble *newArray, DataArrayDouble* &arrayToSet); MEDCOUPLING_EXPORT const double *getConstPointer() const { return _mem.getConstPointer(); } MEDCOUPLING_EXPORT DataArrayDoubleIterator *iterator(); @@ -527,7 +527,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT int back() const; MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, int newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; declareAsNew(); } MEDCOUPLING_EXPORT void setIJSilent(int tupleId, int compoId, int newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; } - MEDCOUPLING_EXPORT int *getPointer() { return _mem.getPointer(); } + MEDCOUPLING_EXPORT int *getPointer() { return _mem.getPointer(); declareAsNew(); } MEDCOUPLING_EXPORT static void SetArrayIn(DataArrayInt *newArray, DataArrayInt* &arrayToSet); MEDCOUPLING_EXPORT const int *getConstPointer() const { return _mem.getConstPointer(); } MEDCOUPLING_EXPORT DataArrayIntIterator *iterator(); @@ -727,7 +727,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT char back() const; MEDCOUPLING_EXPORT void setIJ(int tupleId, int compoId, char newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; declareAsNew(); } MEDCOUPLING_EXPORT void setIJSilent(int tupleId, int compoId, char newVal) { _mem[tupleId*_info_on_compo.size()+compoId]=newVal; } - MEDCOUPLING_EXPORT char *getPointer() { return _mem.getPointer(); } + MEDCOUPLING_EXPORT char *getPointer() { return _mem.getPointer(); declareAsNew(); } MEDCOUPLING_EXPORT const char *getConstPointer() const { return _mem.getConstPointer(); } MEDCOUPLING_EXPORT const char *begin() const { return getConstPointer(); } MEDCOUPLING_EXPORT const char *end() const { return getConstPointer()+getNbOfElems(); } diff --git a/src/MEDCoupling/MEDCouplingPointSet.hxx b/src/MEDCoupling/MEDCouplingPointSet.hxx index c9bdc4e55..59307c6a8 100644 --- a/src/MEDCoupling/MEDCouplingPointSet.hxx +++ b/src/MEDCoupling/MEDCouplingPointSet.hxx @@ -24,6 +24,7 @@ #include "MEDCoupling.hxx" #include "MEDCouplingMesh.hxx" +#include #include namespace INTERP_KERNEL @@ -119,9 +120,11 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT virtual DataArrayInt *findBoundaryNodes() const = 0; MEDCOUPLING_EXPORT virtual MEDCouplingPointSet *buildBoundaryMesh(bool keepCoords) const = 0; MEDCOUPLING_EXPORT virtual int getNumberOfNodesInCell(int cellId) const = 0; + MEDCOUPLING_EXPORT virtual DataArrayInt *computeFetchedNodeIds() const = 0; 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 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 d8ba41453..41784fb2f 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -1425,10 +1425,8 @@ DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const */ void MEDCouplingUMesh::computeNodeIdsAlg(std::vector& nodeIdsInUse) const { - int nbOfNodes=(int)nodeIdsInUse.size(); - int nbOfCells=getNumberOfCells(); - const int *connIndex=_nodal_connec_index->getConstPointer(); - const int *conn=_nodal_connec->getConstPointer(); + int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells()); + const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer()); for(int i=0;i=0) @@ -1437,7 +1435,7 @@ void MEDCouplingUMesh::computeNodeIdsAlg(std::vector& nodeIdsInUse) const nodeIdsInUse[conn[j]]=true; else { - std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !"; + std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } } @@ -1460,12 +1458,12 @@ void MEDCouplingUMesh::computeNodeIdsAlg(std::vector& nodeIdsInUse) const * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".
* \ref py_mcumesh_getNodeIdsInUse "Here is a Python example". * \endif - * \sa computeNodeIdsAlg() + * \sa computeFetchedNodeIds, computeNodeIdsAlg() */ DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const { nbrOfNodesInUse=-1; - int nbOfNodes=getNumberOfNodes(); + int nbOfNodes(getNumberOfNodes()); MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1); int *traducer=ret->getPointer(); @@ -2499,6 +2497,39 @@ void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes); } +/*! + * 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) +{ + checkConnectivityFullyDefined(); + int *conn(getNodalConnectivity()->getPointer()); + const int *connIndex(getNodalConnectivityIndex()->getConstPointer()); + int nbOfCells=getNumberOfCells(); + for(int i=0;i=0)//avoid polyhedron separator + { + std::map::const_iterator it(newNodeNumbersO2N.find(node)); + if(it!=newNodeNumbersO2N.end()) + { + node=(*it).second; + } + else + { + std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } + _nodal_connec->declareAsNew(); + updateTime(); +} + /*! * Changes ids of nodes within the nodal connectivity arrays according to a permutation * array in "Old to New" mode. The node coordinates array is \b not changed by this method. diff --git a/src/MEDCoupling/MEDCouplingUMesh.hxx b/src/MEDCoupling/MEDCouplingUMesh.hxx index 7f3aa5d7b..38adadf3d 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.hxx +++ b/src/MEDCoupling/MEDCouplingUMesh.hxx @@ -140,6 +140,7 @@ namespace ParaMEDMEM MEDCOUPLING_EXPORT void findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate, DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const; MEDCOUPLING_EXPORT void duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd); + MEDCOUPLING_EXPORT void renumberNodesInConn(const std::map& 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/MEDCouplingBasicsTest.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py index 19301bb7d..0587b0f97 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest.py @@ -15905,6 +15905,20 @@ class MEDCouplingBasicsTest(unittest.TestCase): self.assertTrue(d.isEqual(DataArrayDouble([(7.,7.),(7.,7.),(7.,7.)]),1e-12)) pass + def testSwig2PointSetComputeFetchedNodeIds1(self): + arr=DataArrayDouble(6) ; arr.iota() + m=MEDCouplingCMesh() ; m.setCoords(arr,arr,arr) + m=m.buildUnstructured() + m0=m[[0,1,5,6,25,26,30,31,124]] + ref=DataArrayInt([0,1,2,6,7,8,12,13,14,36,37,38,42,43,44,48,49,50,72,73,74,78,79,80,84,85,86,172,173,178,179,208,209,214,215]) + self.assertTrue(m0.computeFetchedNodeIds().isEqual(ref)) + self.assertTrue(MEDCoupling1SGTUMesh(m0).computeFetchedNodeIds().isEqual(ref)) + self.assertEqual(m0.getAllGeoTypes(),[NORM_HEXA8]) + m0.convertAllToPoly() + self.assertEqual(m0.getAllGeoTypes(),[NORM_POLYHED]) + self.assertTrue(MEDCoupling1DGTUMesh(m0).computeFetchedNodeIds().isEqual(ref)) + pass + pass if __name__ == '__main__': diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index b0928bc92..01bc5e64c 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -245,6 +245,7 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::MEDCouplingPointSet::getCellIdsLyingOnNodes; %newobject ParaMEDMEM::MEDCouplingPointSet::deepCpyConnectivityOnly; %newobject ParaMEDMEM::MEDCouplingPointSet::getBoundingBoxForBBTree; +%newobject ParaMEDMEM::MEDCouplingPointSet::computeFetchedNodeIds; %newobject ParaMEDMEM::MEDCouplingPointSet::ComputeNbOfInteractionsWithSrcCells; %newobject ParaMEDMEM::MEDCouplingPointSet::__getitem__; %newobject ParaMEDMEM::MEDCouplingUMesh::New; @@ -269,7 +270,6 @@ using namespace INTERP_KERNEL; %newobject ParaMEDMEM::MEDCouplingUMesh::sortCellsInMEDFileFrmt; %newobject ParaMEDMEM::MEDCouplingUMesh::getRenumArrForMEDFileFrmt; %newobject ParaMEDMEM::MEDCouplingUMesh::convertCellArrayPerGeoType; -%newobject ParaMEDMEM::MEDCouplingUMesh::computeFetchedNodeIds; %newobject ParaMEDMEM::MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec; %newobject ParaMEDMEM::MEDCouplingUMesh::buildDirectionVectorField; %newobject ParaMEDMEM::MEDCouplingUMesh::convertLinearCellsToQuadratic; @@ -1040,6 +1040,7 @@ namespace ParaMEDMEM static DataArrayDouble *MergeNodesArray(const MEDCouplingPointSet *m1, const MEDCouplingPointSet *m2) throw(INTERP_KERNEL::Exception); static MEDCouplingPointSet *BuildInstanceFromMeshType(MEDCouplingMeshType type) throw(INTERP_KERNEL::Exception); static DataArrayInt *ComputeNbOfInteractionsWithSrcCells(const MEDCouplingPointSet *srcMesh, const MEDCouplingPointSet *trgMesh, double eps) throw(INTERP_KERNEL::Exception); + virtual DataArrayInt *computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception); virtual int getNumberOfNodesInCell(int cellId) const throw(INTERP_KERNEL::Exception); virtual MEDCouplingPointSet *buildBoundaryMesh(bool keepCoords) const throw(INTERP_KERNEL::Exception); virtual DataArrayInt *getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps) throw(INTERP_KERNEL::Exception); @@ -1631,7 +1632,6 @@ namespace ParaMEDMEM DataArrayInt *sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception); DataArrayInt *getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception); DataArrayInt *convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception); - DataArrayInt *computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception); MEDCouplingUMesh *buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception); MEDCouplingUMesh *buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception); MEDCouplingUMesh *explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception); diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index 95a947585..aad1dfd60 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -1983,6 +1983,40 @@ MEDFileUMesh *MEDFileUMesh::New() return new MEDFileUMesh; } +/*! + * This method loads from file with name \a fileName the mesh called \a mName as New does. The difference is that + * here only a part of cells contained in the file will be loaded. The selection of cell is specified using the two consecutive parameters + * \a types and \a slicPerTyp. This method allows to load from a mesh (typically huge) in a MED file a part of cells of that mesh. + * The part of cells is specified using triplet (start,stop,step) for each geometric type. Only nodes lying on selected cells will be loaded to reduce + * at most the memory consumtion. + * + * \param [in] fileName - the name of the file. + * \param [in] mName - the name of the mesh to be read. + * \param [in] types - the list of the geo types of which some part will be taken. A geometric type in \a types must appear only once at most. + * \param [in] slicPerType - an array of size 3 times larger than \a types that specifies for each type in \a types (in the same order) resp the start, the stop and the step. + * \param [in] dt - the iteration, that is to say the first element of the pair that locates the asked time step. + * \param [in] it - the order, that is to say the second element of the pair that locates the asked time step. + * \param [in] mrs - the request for what to be loaded. + * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this mesh using decrRef() as it is no more needed. + */ +MEDFileUMesh *MEDFileUMesh::LoadPartOf(const std::string& fileName, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid(MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY)); + return MEDFileUMesh::LoadPartOf(fid,mName,types,slicPerTyp,dt,it,mrs); +} + +/*! + * Please refer to the other MEDFileUMesh::LoadPartOf method that has the same semantic and the same parameter (excepted the first). + * This method is \b NOT wrapped into python. + */ +MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + MEDCouplingAutoRefCountObjectPtr ret(MEDFileUMesh::New()); + ret->loadPartUMeshFromFile(fid,mName,types,slicPerTyp,dt,it,mrs); + return ret.retn(); +} + std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const { std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren()); @@ -2192,19 +2226,52 @@ catch(INTERP_KERNEL::Exception& e) throw e; } +/*! + * This method loads only a part of specified cells (given by range of cell ID per geometric type) + * See MEDFileUMesh::LoadPartOf for detailed description. + * + * \sa loadUMeshFromFile + */ +void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + MEDFileUMeshL2 loaderl2; + ParaMEDMEM::MEDCouplingMeshType meshType; + int dummy0,dummy1; + std::string dummy2; + int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2)); + if(meshType!=UNSTRUCTURED) + { + std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs); + dispatchLoadedPart(fid,loaderl2,mName,mrs); +} + +/*! + * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor. + * + * \sa loadPartUMeshFromFile + */ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { MEDFileUMeshL2 loaderl2; ParaMEDMEM::MEDCouplingMeshType meshType; int dummy0,dummy1; std::string dummy2; - int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2); + int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2)); if(meshType!=UNSTRUCTURED) { std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } loaderl2.loadAll(fid,mid,mName,dt,it,mrs); + dispatchLoadedPart(fid,loaderl2,mName,mrs); + +} + +void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs) +{ int lev=loaderl2.getNumberOfLevels(); _ms.resize(lev); for(int i=0;i& types, const std::vector& slicPerTyp, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0); + MEDLOADER_EXPORT static MEDFileUMesh *LoadPartOf(med_idt fid, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0); MEDLOADER_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; MEDLOADER_EXPORT std::vector getDirectChildrenWithNull() const; MEDLOADER_EXPORT MEDFileMesh *createNewEmpty() const; @@ -284,7 +286,9 @@ namespace ParaMEDMEM void writeLL(med_idt fid) const; MEDFileUMesh(); MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs); + void loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0); void loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs); + void dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs); const MEDFileUMeshSplitL1 *getMeshAtLevSafe(int meshDimRelToMaxExt) const; MEDFileUMeshSplitL1 *getMeshAtLevSafe(int meshDimRelToMaxExt); void checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const; diff --git a/src/MEDLoader/MEDFileMeshElt.cxx b/src/MEDLoader/MEDFileMeshElt.cxx index 00980e5b1..ce16d0da1 100644 --- a/src/MEDLoader/MEDFileMeshElt.cxx +++ b/src/MEDLoader/MEDFileMeshElt.cxx @@ -23,6 +23,7 @@ #include "MEDCouplingUMesh.hxx" +#include "InterpKernelException.hxx" #include "InterpKernelAutoPtr.hxx" #include "CellModel.hxx" @@ -40,6 +41,20 @@ MEDFileUMeshPerType *MEDFileUMeshPerType::New(med_idt fid, const char *mName, in return new MEDFileUMeshPerType(fid,mName,dt,it,mdim,geoElt,geoElt2,whichEntity,mrs); } +MEDFileUMeshPerType *MEDFileUMeshPerType::NewPart(med_idt fid, const char *mName, int dt, int it, int mdim, INTERP_KERNEL::NormalizedCellType geoElt2, int strt, int stp, int step, MEDFileMeshReadSelector *mrs) +{ + int geoElt2i((int)geoElt2); + if(geoElt2i<0 || geoElt2i>=34) + throw INTERP_KERNEL::Exception("MEDFileUMeshPerType::NewPart : Not recognized MEDCoupling/MEDLoader geometric type !"); + med_geometry_type geoElt(typmai3[geoElt2]); + med_entity_type whichEntity; + if(!isExisting(fid,mName,dt,it,geoElt,whichEntity)) + throw INTERP_KERNEL::Exception("MEDFileUMeshPerType::NewPart : The specified geo type is not present in the specified mesh !"); + MEDCouplingAutoRefCountObjectPtr ret(new MEDFileUMeshPerType); + ret->loadPart(fid,mName,dt,it,mdim,geoElt,geoElt2,whichEntity,strt,stp,step,mrs); + return ret.retn(); +} + std::size_t MEDFileUMeshPerType::getHeapMemorySizeWithoutChildren() const { return 0; @@ -62,8 +77,7 @@ bool MEDFileUMeshPerType::isExisting(med_idt fid, const char *mName, int dt, int for(int i=0;i<3;i++) { med_bool changement,transformation; - int tmp=MEDmeshnEntity(fid,mName,dt,it,entities[i],geoElt,MED_CONNECTIVITY,MED_NODAL, - &changement,&transformation); + int tmp=MEDmeshnEntity(fid,mName,dt,it,entities[i],geoElt,MED_CONNECTIVITY,MED_NODAL,&changement,&transformation); if(tmp>nbOfElt) { nbOfElt=tmp; @@ -80,13 +94,16 @@ int MEDFileUMeshPerType::getDim() const return _m->getMeshDimension(); } +MEDFileUMeshPerType::MEDFileUMeshPerType() +{ +} + MEDFileUMeshPerType::MEDFileUMeshPerType(med_idt fid, const char *mName, int dt, int it, int mdim, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, med_entity_type entity, MEDFileMeshReadSelector *mrs):_entity(entity) { med_bool changement,transformation; - int curNbOfElem=MEDmeshnEntity(fid,mName,dt,it,entity,geoElt,MED_CONNECTIVITY,MED_NODAL, - &changement,&transformation); - const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type); + int curNbOfElem(MEDmeshnEntity(fid,mName,dt,it,entity,geoElt,MED_CONNECTIVITY,MED_NODAL,&changement,&transformation)); + const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type)); if(!cm.isDynamic()) { loadFromStaticType(fid,mName,dt,it,mdim,curNbOfElem,geoElt,type,entity,mrs); @@ -101,13 +118,27 @@ MEDFileUMeshPerType::MEDFileUMeshPerType(med_idt fid, const char *mName, int dt, loadPolyh(fid,mName,dt,it,mdim,curNbOfElem,geoElt,entity,mrs); } +void MEDFileUMeshPerType::loadPart(med_idt fid, const char *mName, int dt, int it, int mdim, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, + med_entity_type entity, int strt, int end, int step, MEDFileMeshReadSelector *mrs) +{ + med_bool changement,transformation; + int curNbOfElem(MEDmeshnEntity(fid,mName,dt,it,entity,geoElt,MED_CONNECTIVITY,MED_NODAL,&changement,&transformation)); + const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type)); + if(!cm.isDynamic()) + { + loadPartStaticType(fid,mName,dt,it,mdim,curNbOfElem,geoElt,type,entity,strt,end,step,mrs); + } + else + throw INTERP_KERNEL::Exception("MEDFileUMeshPerType::loadPart : not implemented yet for the dynamic type !"); +} + void MEDFileUMeshPerType::loadFromStaticType(med_idt fid, const char *mName, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, med_entity_type entity, MEDFileMeshReadSelector *mrs) { _m=MEDCoupling1SGTUMesh::New(mName,type); MEDCoupling1SGTUMesh *mc(dynamic_cast((MEDCoupling1GTUMesh *)_m)); MEDCouplingAutoRefCountObjectPtr conn(DataArrayInt::New()); - int nbOfNodesPerCell=mc->getNumberOfNodesPerCell(); + int nbOfNodesPerCell(mc->getNumberOfNodesPerCell()); conn->alloc(nbOfNodesPerCell*curNbOfElem,1); MEDmeshElementConnectivityRd(fid,mName,dt,it,entity,geoElt,MED_NODAL,MED_FULL_INTERLACE,conn->getPointer()); std::transform(conn->begin(),conn->end(),conn->getPointer(),std::bind2nd(std::plus(),-1)); @@ -115,6 +146,31 @@ void MEDFileUMeshPerType::loadFromStaticType(med_idt fid, const char *mName, int loadCommonPart(fid,mName,dt,it,mdim,curNbOfElem,geoElt,entity,mrs); } +void MEDFileUMeshPerType::loadPartStaticType(med_idt fid, const char *mName, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, + med_entity_type entity, int strt, int end, int step, MEDFileMeshReadSelector *mrs) +{ + if(strt<0) + throw INTERP_KERNEL::Exception("MEDFileUMeshPerType::loadPartStaticType : start pos is negative !"); + if(end>curNbOfElem) + throw INTERP_KERNEL::Exception("MEDFileUMeshPerType::loadPartStaticType : end is after the authorized range !"); + int nbOfEltsToLoad(DataArray::GetNumberOfItemGivenBES(strt,end,step,"MEDFileUMeshPerType::loadPartStaticType")); + _m=MEDCoupling1SGTUMesh::New(mName,type); + MEDCoupling1SGTUMesh *mc(dynamic_cast((MEDCoupling1GTUMesh *)_m)); + MEDCouplingAutoRefCountObjectPtr conn(DataArrayInt::New()); + int nbOfNodesPerCell(mc->getNumberOfNodesPerCell()); + conn->alloc(nbOfNodesPerCell*nbOfEltsToLoad,1); + med_filter filter=MED_FILTER_INIT; + MEDfilterBlockOfEntityCr(fid,/*nentity*/curNbOfElem,/*nvaluesperentity*/1,/*nconstituentpervalue*/nbOfNodesPerCell, + MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE, + /*start*/strt+1,/*stride*/step,/*count*/1,/*blocksize*/nbOfEltsToLoad, + /*lastblocksize=useless because count=1*/0,&filter); + MEDmeshElementConnectivityAdvancedRd(fid,mName,dt,it,entity,geoElt,MED_NODAL,&filter,conn->getPointer()); + MEDfilterClose(&filter); + std::transform(conn->begin(),conn->end(),conn->getPointer(),std::bind2nd(std::plus(),-1)); + mc->setNodalConnectivity(conn); + loadPartOfCellCommonPart(fid,mName,strt,end,step,dt,it,mdim,curNbOfElem,geoElt,entity,mrs); +} + void MEDFileUMeshPerType::loadCommonPart(med_idt fid, const char *mName, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs) { @@ -156,6 +212,65 @@ void MEDFileUMeshPerType::loadCommonPart(med_idt fid, const char *mName, int dt, } } +void MEDFileUMeshPerType::loadPartOfCellCommonPart(med_idt fid, const char *mName, int strt, int stp, int step, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs) +{ + med_bool changement,transformation; + _fam=0; + int nbOfEltsToLoad(DataArray::GetNumberOfItemGivenBES(strt,stp,step,"MEDFileUMeshPerType::loadPartOfCellCommonPart")); + if(MEDmeshnEntity(fid,mName,dt,it,entity,geoElt,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0) + { + if(!mrs || mrs->isCellFamilyFieldReading()) + { + _fam=DataArrayInt::New(); + _fam->alloc(nbOfEltsToLoad,1); + med_filter filter=MED_FILTER_INIT; + MEDfilterBlockOfEntityCr(fid,/*nentity*/curNbOfElem,/*nvaluesperentity*/1,/*nconstituentpervalue*/1, + MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE, + /*start*/strt+1,/*stride*/step,/*count*/1,/*blocksize*/nbOfEltsToLoad, + /*lastblocksize=useless because count=1*/0,&filter); + if(MEDmeshEntityAttributeAdvancedRd(fid,mName,MED_FAMILY_NUMBER,dt,it,entity,geoElt,&filter,_fam->getPointer())!=0) + _fam->fillWithZero(); + MEDfilterClose(&filter); + } + } + _num=0; + if(MEDmeshnEntity(fid,mName,dt,it,entity,geoElt,MED_NUMBER,MED_NODAL,&changement,&transformation)>0) + { + if(!mrs || mrs->isCellNumFieldReading()) + { + _num=DataArrayInt::New(); + _num->alloc(nbOfEltsToLoad,1); + med_filter filter=MED_FILTER_INIT; + MEDfilterBlockOfEntityCr(fid,/*nentity*/curNbOfElem,/*nvaluesperentity*/1,/*nconstituentpervalue*/1, + MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE, + /*start*/strt+1,/*stride*/step,/*count*/1,/*blocksize*/nbOfEltsToLoad, + /*lastblocksize=useless because count=1*/0,&filter); + if(MEDmeshEntityAttributeAdvancedRd(fid,mName,MED_NUMBER,dt,it,entity,geoElt,&filter,_num->getPointer())!=0) + _num->fillWithZero(); + MEDfilterClose(&filter); + } + } + _names=0; + if(MEDmeshnEntity(fid,mName,dt,it,entity,geoElt,MED_NAME,MED_NODAL,&changement,&transformation)>0) + { + if(!mrs || mrs->isCellNameFieldReading()) + { + _names=DataArrayAsciiChar::New(); + _names->alloc(nbOfEltsToLoad+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end + med_filter filter=MED_FILTER_INIT; + MEDfilterBlockOfEntityCr(fid,/*nentity*/curNbOfElem,/*nvaluesperentity*/1,/*nconstituentpervalue*/1, + MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE, + /*start*/strt+1,/*stride*/step,/*count*/1,/*blocksize*/nbOfEltsToLoad, + /*lastblocksize=useless because count=1*/0,&filter); + if(MEDmeshEntityAttributeAdvancedRd(fid,mName,MED_NAME,dt,it,entity,geoElt,&filter,_names->getPointer())!=0) + _names=0; + else + _names->reAlloc(nbOfEltsToLoad);//not a bug to avoid the memory corruption due to last \0 at the end + MEDfilterClose(&filter); + } + } +} + void MEDFileUMeshPerType::loadPolyg(med_idt fid, const char *mName, int dt, int it, int mdim, int arraySize, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs) { diff --git a/src/MEDLoader/MEDFileMeshElt.hxx b/src/MEDLoader/MEDFileMeshElt.hxx index 93be1e338..ed795f159 100644 --- a/src/MEDLoader/MEDFileMeshElt.hxx +++ b/src/MEDLoader/MEDFileMeshElt.hxx @@ -38,6 +38,7 @@ namespace ParaMEDMEM { public: static MEDFileUMeshPerType *New(med_idt fid, const char *mName, int dt, int it, int mdim, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType geoElt2, MEDFileMeshReadSelector *mrs); + static MEDFileUMeshPerType *NewPart(med_idt fid, const char *mName, int dt, int it, int mdim, INTERP_KERNEL::NormalizedCellType geoElt2, int strt, int stp, int step, MEDFileMeshReadSelector *mrs); static bool isExisting(med_idt fid, const char *mName, int dt, int it, med_geometry_type geoElt, med_entity_type& whichEntity); std::size_t getHeapMemorySizeWithoutChildren() const; std::vector getDirectChildrenWithNull() const; @@ -48,15 +49,21 @@ namespace ParaMEDMEM const DataArrayAsciiChar *getNames() const { return _names; } static void Write(med_idt fid, const std::string& mname, int mdim, const MEDCoupling1GTUMesh *m, const DataArrayInt *fam, const DataArrayInt *num, const DataArrayAsciiChar *names); private: + MEDFileUMeshPerType(); MEDFileUMeshPerType(med_idt fid, const char *mName, int dt, int it, int mdim, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, med_entity_type entity, MEDFileMeshReadSelector *mrs); + void loadPart(med_idt fid, const char *mName, int dt, int it, int mdim, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, + med_entity_type entity, int strt, int end, int step, MEDFileMeshReadSelector *mrs); void loadFromStaticType(med_idt fid, const char *mName, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, med_entity_type entity, MEDFileMeshReadSelector *mrs); + void loadPartStaticType(med_idt fid, const char *mName, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, INTERP_KERNEL::NormalizedCellType type, + med_entity_type entity, int strt, int end, int step, MEDFileMeshReadSelector *mrs); void loadPolyg(med_idt fid, const char *mName, int dt, int it, int mdim, int arraySize, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs); void loadPolyh(med_idt fid, const char *mName, int dt, int it, int mdim, int connFaceLgth, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs); void loadCommonPart(med_idt fid, const char *mName, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs); + void loadPartOfCellCommonPart(med_idt fid, const char *mName, int strt, int stp, int step, int dt, int it, int mdim, int curNbOfElem, med_geometry_type geoElt, med_entity_type entity, MEDFileMeshReadSelector *mrs); private: MEDCouplingAutoRefCountObjectPtr _m; MEDCouplingAutoRefCountObjectPtr _num; diff --git a/src/MEDLoader/MEDFileMeshLL.cxx b/src/MEDLoader/MEDFileMeshLL.cxx index bd8aff2c4..344f61447 100644 --- a/src/MEDLoader/MEDFileMeshLL.cxx +++ b/src/MEDLoader/MEDFileMeshLL.cxx @@ -243,45 +243,100 @@ MEDFileUMeshL2::MEDFileUMeshL2() { } -void MEDFileUMeshL2::loadAll(med_idt fid, int mId, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +std::vector MEDFileUMeshL2::loadCommonPart(med_idt fid, int mId, const std::string& mName, int dt, int it, int& Mdim) { + Mdim=-3; _name.set(mName.c_str()); int nstep; - int Mdim; ParaMEDMEM::MEDCouplingMeshType meshType; - std::vector infosOnComp=getAxisInfoOnMesh(fid,mId,mName.c_str(),meshType,nstep,Mdim); + std::vector ret(getAxisInfoOnMesh(fid,mId,mName.c_str(),meshType,nstep,Mdim)); if(nstep==0) - return ; + { + Mdim=-4; + return std::vector(); + } if(meshType!=UNSTRUCTURED) throw INTERP_KERNEL::Exception("Invalid mesh type ! You are expected an unstructured one whereas in file it is not an unstructured !"); _time=CheckMeshTimeStep(fid,mName,nstep,dt,it); _iteration=dt; _order=it; + return ret; +} + +void MEDFileUMeshL2::loadAll(med_idt fid, int mId, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + int Mdim; + std::vector infosOnComp(loadCommonPart(fid,mId,mName,dt,it,Mdim)); + if(Mdim==-4) + return ; loadConnectivity(fid,Mdim,mName,dt,it,mrs);//to improve check (dt,it) coherency loadCoords(fid,mId,infosOnComp,mName,dt,it); } +void MEDFileUMeshL2::loadPart(med_idt fid, int mId, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + int Mdim; + std::vector infosOnComp(loadCommonPart(fid,mId,mName,dt,it,Mdim)); + if(Mdim==-4) + return ; + loadPartOfConnectivity(fid,Mdim,mName,types,slicPerTyp,dt,it,mrs); + med_bool changement,transformation; + int nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation)); + std::vector fetchedNodeIds(nCoords,false); + 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; + 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); +} + void MEDFileUMeshL2::loadConnectivity(med_idt fid, int mdim, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { _per_type_mesh.resize(1); _per_type_mesh[0].clear(); for(int j=0;j& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + std::size_t nbOfTypes(types.size()); + if(slicPerTyp.size()!=3*nbOfTypes) + throw INTERP_KERNEL::Exception("MEDFileUMeshL2::loadPartOfConnectivity : The size of slicPerTyp array is expected to be equal to 3 times size of array types !"); + std::set types2(types.begin(),types.end()); + if(types2.size()!=nbOfTypes) + throw INTERP_KERNEL::Exception("MEDFileUMeshL2::loadPartOfConnectivity : the geometric types in types array must appear once !"); + _per_type_mesh.resize(1); + _per_type_mesh[0].clear(); + for(std::size_t ii=0;ii tmp(MEDFileUMeshPerType::NewPart(fid,mName.c_str(),dt,it,mdim,types[ii],strt,stp,step,mrs)); + _per_type_mesh[0].push_back(tmp); + } + sortTypes(); +} + void MEDFileUMeshL2::loadCoords(med_idt fid, int mId, const std::vector& infosOnComp, const std::string& mName, int dt, int it) { - int spaceDim=infosOnComp.size(); + int spaceDim((int)infosOnComp.size()); med_bool changement,transformation; - int nCoords=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation); + int nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation)); _coords=DataArrayDouble::New(); _coords->alloc(nCoords,spaceDim); - double *coordsPtr=_coords->getPointer(); + double *coordsPtr(_coords->getPointer()); MEDmeshNodeCoordinateRd(fid,mName.c_str(),dt,it,MED_FULL_INTERLACE,coordsPtr); if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0) { @@ -312,6 +367,57 @@ 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) +{ + 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)); + _coords=DataArrayDouble::New(); + _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); + 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); + 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(); + _fam_coords->alloc(nbNodesToLoad,1); + MEDmeshEntityAttributeAdvancedRd(fid,mName.c_str(),MED_FAMILY_NUMBER,dt,it,MED_NODE,MED_NO_GEOTYPE,&filter2,_fam_coords->getPointer()); + } + else + _fam_coords=0; + if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NUMBER,MED_NODAL,&changement,&transformation)>0) + { + _num_coords=DataArrayInt::New(); + _num_coords->alloc(nbNodesToLoad,1); + MEDmeshEntityAttributeAdvancedRd(fid,mName.c_str(),MED_NUMBER,dt,it,MED_NODE,MED_NO_GEOTYPE,&filter2,_num_coords->getPointer()); + } + else + _num_coords=0; + if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_NAME,MED_NODAL,&changement,&transformation)>0) + { + _name_coords=DataArrayAsciiChar::New(); + _name_coords->alloc(nbNodesToLoad+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end + MEDmeshEntityAttributeAdvancedRd(fid,mName.c_str(),MED_NAME,dt,it,MED_NODE,MED_NO_GEOTYPE,&filter2,_name_coords->getPointer()); + _name_coords->reAlloc(nbNodesToLoad);//not a bug to avoid the memory corruption due to last \0 at the end + } + else + _name_coords=0; + n2o->applyLin(1,-1);//FORTRAN -> C + MEDfilterClose(&filter2); + _coords->setInfoOnComponents(infosOnComp); +} + void MEDFileUMeshL2::sortTypes() { std::set mdims; diff --git a/src/MEDLoader/MEDFileMeshLL.hxx b/src/MEDLoader/MEDFileMeshLL.hxx index ffb34e35a..d2863a507 100644 --- a/src/MEDLoader/MEDFileMeshLL.hxx +++ b/src/MEDLoader/MEDFileMeshLL.hxx @@ -50,7 +50,7 @@ namespace ParaMEDMEM const char *getTimeUnit() const { return _dt_unit.getReprForWrite(); } int getIteration() const { return _iteration; } int getOrder() const { return _order; } - double getTime() { return _time; } + double getTime() const { return _time; } std::vector getAxisInfoOnMesh(med_idt fid, int mId, const std::string& mName, ParaMEDMEM::MEDCouplingMeshType& meshType, int& nstep, int& Mdim); static int GetMeshIdFromName(med_idt fid, const std::string& mName, ParaMEDMEM::MEDCouplingMeshType& meshType, int& dt, int& it, std::string& dtunit1); static double CheckMeshTimeStep(med_idt fid, const std::string& mname, int nstep, int dt, int it); @@ -70,9 +70,13 @@ namespace ParaMEDMEM { public: MEDFileUMeshL2(); + std::vector loadCommonPart(med_idt fid, int mId, const std::string& mName, int dt, int it, int& Mdim); void loadAll(med_idt fid, int mId, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs); + void loadPart(med_idt fid, int mId, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs); 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); 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]; } diff --git a/src/MEDLoader/Swig/MEDLoaderCommon.i b/src/MEDLoader/Swig/MEDLoaderCommon.i index 7a53ab79b..3efbfad25 100644 --- a/src/MEDLoader/Swig/MEDLoaderCommon.i +++ b/src/MEDLoader/Swig/MEDLoaderCommon.i @@ -95,6 +95,7 @@ using namespace ParaMEDMEM; %newobject ParaMEDMEM::MEDFileMesh::computeAllFamilyIdsInUse; %newobject ParaMEDMEM::MEDFileStructuredMesh::getImplicitFaceMesh; %newobject ParaMEDMEM::MEDFileUMesh::New; +%newobject ParaMEDMEM::MEDFileUMesh::LoadPartOf; %newobject ParaMEDMEM::MEDFileUMesh::getCoords; %newobject ParaMEDMEM::MEDFileUMesh::getGroup; %newobject ParaMEDMEM::MEDFileUMesh::getGroups; @@ -783,6 +784,17 @@ namespace ParaMEDMEM { return MEDFileUMesh::New(); } + + static MEDFileUMesh *LoadPartOf(const std::string& fileName, const std::string& mName, PyObject *types, const std::vector& slicPerTyp, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0) throw(INTERP_KERNEL::Exception) + { + std::vector typesCpp1; + convertPyToNewIntArr3(types,typesCpp1); + std::size_t sz(typesCpp1.size()); + std::vector typesCpp2(sz); + for(std::size_t ii=0;ii ret(MEDFileUMesh::New()); + MEDFileUtilities::AutoFid fid(MEDparFileOpen(fileName.c_str(),MED_ACC_RDONLY,com,nfo)); + // + int meshDim, spaceDim, numberOfNodes; + std::vector< std::vector< std::pair > > typesDistrib(MEDLoader::GetUMeshGlobalInfo(fileName,mName,meshDim,spaceDim,numberOfNodes)); + return ret.retn(); +} + +MEDFileMeshes *ParaMEDFileMeshes::New(const MPI_Comm com, const MPI_Info nfo, const std::string& fileName) +{ + std::vector ms(MEDLoader::GetMeshNames(fileName)); + MEDCouplingAutoRefCountObjectPtr ret(MEDFileMeshes::New()); + for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++) + { + MEDCouplingAutoRefCountObjectPtr mesh(ParaMEDFileMesh::New(com,nfo,fileName,(*it))); + ret->pushMesh(mesh); + } + return ret.retn(); +} diff --git a/src/ParaMEDLoader/ParaMEDFileMesh.hxx b/src/ParaMEDLoader/ParaMEDFileMesh.hxx new file mode 100644 index 000000000..52d5697a8 --- /dev/null +++ b/src/ParaMEDLoader/ParaMEDFileMesh.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2014 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, or (at your option) any later version. +// +// 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 +// +// Author : Anthony Geay (EDF R&D) + +#ifndef __PARAMEDFILEMESH_HXX__ +#define __PARAMEDFILEMESH_HXX__ + +#include "mpi.h" + +#include + +namespace ParaMEDMEM +{ + class MEDFileMesh; + class MEDFileUMesh; + class MEDFileMeshes; + class MEDFileMeshReadSelector; + + class ParaMEDFileMesh + { + public: + static MEDFileMesh *New(const MPI_Comm com, const MPI_Info nfo, const std::string& fileName, const std::string& mName, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0); + }; + + class ParaMEDFileUMesh + { + public: + static MEDFileUMesh *New(const MPI_Comm com, const MPI_Info nfo, const std::string& fileName, const std::string& mName, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0); + }; + + class ParaMEDFileMeshes + { + public: + static MEDFileMeshes *New(const MPI_Comm com, const MPI_Info nfo, const std::string& fileName); + }; +} + +#endif