]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Improve performance on // read of a MED file using block filter for nodes instead...
authorAnthony Geay <anthony.geay@edf.fr>
Tue, 30 Sep 2014 12:02:19 +0000 (14:02 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Tue, 30 Sep 2014 12:02:19 +0000 (14:02 +0200)
src/MEDCoupling/MEDCoupling1GTUMesh.cxx
src/MEDCoupling/MEDCoupling1GTUMesh.hxx
src/MEDCoupling/MEDCouplingPointSet.hxx
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling_Swig/MEDCouplingCommon.i
src/MEDLoader/MEDFileMeshLL.cxx
src/MEDLoader/MEDFileMeshLL.hxx

index 5c9b32456e90af479f2a1f16d08a20247eb7c2cd..a13cb0b4f45667c4d7de51e67ddb65dea22e554a 100644 (file)
@@ -1067,12 +1067,27 @@ DataArrayInt *MEDCoupling1SGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
   return ret.retn();
 }
 
+/*!
+ * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
+ * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
+ *
+ * \param [in] offset - specifies the offset to be applied on each element of connectivity.
+ *
+ * \sa renumberNodesInConn
+ */
+void MEDCoupling1SGTUMesh::renumberNodesWithOffsetInConn(int offset)
+{
+  getNumberOfCells();//only to check that all is well defined.
+  _conn->applyLin(1,offset);
+  updateTime();
+}
+
 /*!
  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
  *  of a big mesh.
  */
-void MEDCoupling1SGTUMesh::renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N)
+void MEDCoupling1SGTUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
 {
   getNumberOfCells();//only to check that all is well defined.
   int *begPtr(_conn->getPointer());
@@ -1080,7 +1095,7 @@ void MEDCoupling1SGTUMesh::renumberNodesInConn(const std::map<int,int>& newNodeN
   int *endPtr(begPtr+nbElt);
   for(int *it=begPtr;it!=endPtr;it++)
     {
-      std::map<int,int>::const_iterator it2(newNodeNumbersO2N.find(*it));
+      INTERP_KERNEL::HashMap<int,int>::const_iterator it2(newNodeNumbersO2N.find(*it));
       if(it2!=newNodeNumbersO2N.end())
         {
           *it=(*it2).second;
@@ -3093,12 +3108,35 @@ DataArrayInt *MEDCoupling1DGTUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
   return ret.retn();
 }
 
+/*!
+ * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
+ * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
+ *
+ * \param [in] offset - specifies the offset to be applied on each element of connectivity.
+ *
+ * \sa renumberNodesInConn
+ */
+void MEDCoupling1DGTUMesh::renumberNodesWithOffsetInConn(int offset)
+{
+  getNumberOfCells();//only to check that all is well defined.
+  //
+  int nbElemsIn(getNumberOfNodes()),nbOfTuples(_conn->getNumberOfTuples());
+  int *pt(_conn->getPointer());
+  for(int i=0;i<nbOfTuples;i++,pt++)
+    {
+      if(*pt==-1) continue;
+      *pt+=offset;
+    }
+  //
+  updateTime();
+}
+
 /*!
  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
  *  of a big mesh.
  */
-void MEDCoupling1DGTUMesh::renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N)
+void MEDCoupling1DGTUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
 {
   getNumberOfCells();//only to check that all is well defined.
   //
@@ -3109,7 +3147,7 @@ void MEDCoupling1DGTUMesh::renumberNodesInConn(const std::map<int,int>& newNodeN
       if(*pt==-1) continue;
       if(*pt>=0 && *pt<nbElemsIn)
         {
-          std::map<int,int>::const_iterator it(newNodeNumbersO2N.find(*pt));
+          INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(*pt));
           if(it!=newNodeNumbersO2N.end())
             *pt=(*it).second;
           else
index 50169f5abeddf95de43d4f1642b310c59304950f..01c09f0a6f02454715c8c3358f1df0a97cd9496e 100644 (file)
@@ -130,7 +130,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector<int>& tinyInfo) const;
     MEDCOUPLING_EXPORT DataArrayInt *computeFetchedNodeIds() const;
     MEDCOUPLING_EXPORT DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const;
-    MEDCOUPLING_EXPORT void renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N);
+    MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(int offset);
+    MEDCOUPLING_EXPORT void renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N);
     MEDCOUPLING_EXPORT void renumberNodesInConn(const int *newNodeNumbersO2N);
     MEDCOUPLING_EXPORT void fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const;
     MEDCOUPLING_EXPORT int getNumberOfNodesInCell(int cellId) const;
@@ -222,7 +223,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT bool isEmptyMesh(const std::vector<int>& tinyInfo) const;
     MEDCOUPLING_EXPORT DataArrayInt *computeFetchedNodeIds() const;
     MEDCOUPLING_EXPORT DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const;
-    MEDCOUPLING_EXPORT void renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N);
+    MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(int offset);
+    MEDCOUPLING_EXPORT void renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& 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;
index 59307c6a86d0b0cff9ed484a848bbd95cd945b1e..31083d9e8e604075907d529238e0c276256e0a50 100644 (file)
@@ -24,7 +24,8 @@
 #include "MEDCoupling.hxx"
 #include "MEDCouplingMesh.hxx"
 
-#include <map>
+#include "InterpKernelHashMap.hxx"
+
 #include <vector>
 
 namespace INTERP_KERNEL
@@ -124,7 +125,8 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT virtual DataArrayInt *getNodeIdsInUse(int& nbrOfNodesInUse) const = 0;
     MEDCOUPLING_EXPORT virtual void fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const = 0;
     MEDCOUPLING_EXPORT virtual void renumberNodesInConn(const int *newNodeNumbersO2N) = 0;
-    MEDCOUPLING_EXPORT virtual void renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N) = 0;
+    MEDCOUPLING_EXPORT virtual void renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N) = 0;
+    MEDCOUPLING_EXPORT virtual void renumberNodesWithOffsetInConn(int offset) = 0;
     MEDCOUPLING_EXPORT virtual void renumberNodes(const int *newNodeNumbers, int newNbOfNodes);
     MEDCOUPLING_EXPORT virtual void renumberNodes2(const int *newNodeNumbers, int newNbOfNodes);
     MEDCOUPLING_EXPORT virtual bool isEmptyMesh(const std::vector<int>& tinyInfo) const = 0;
index 41784fb2fbebfd2e81d0110352b4853e7e87ce7b..3677ba54d0f0e9790ddb5ecb5e5e0e95eddbf376 100644 (file)
@@ -2497,24 +2497,51 @@ void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int
   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
 }
 
+/*!
+ * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
+ * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
+ *
+ * \param [in] offset - specifies the offset to be applied on each element of connectivity.
+ *
+ * \sa renumberNodesInConn
+ */
+void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
+{
+  checkConnectivityFullyDefined();
+  int *conn(getNodalConnectivity()->getPointer());
+  const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
+  int nbOfCells(getNumberOfCells());
+  for(int i=0;i<nbOfCells;i++)
+    for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
+      {
+        int& node=conn[iconn];
+        if(node>=0)//avoid polyhedron separator
+          {
+            node+=offset;
+          }
+      }
+  _nodal_connec->declareAsNew();
+  updateTime();
+}
+
 /*!
  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
  *  of a big mesh.
  */
-void MEDCouplingUMesh::renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N)
+void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
 {
   checkConnectivityFullyDefined();
   int *conn(getNodalConnectivity()->getPointer());
   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
-  int nbOfCells=getNumberOfCells();
+  int nbOfCells(getNumberOfCells());
   for(int i=0;i<nbOfCells;i++)
     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
       {
         int& node=conn[iconn];
         if(node>=0)//avoid polyhedron separator
           {
-            std::map<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
+            INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
             if(it!=newNodeNumbersO2N.end())
               {
                 node=(*it).second;
@@ -2550,7 +2577,7 @@ void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
   checkConnectivityFullyDefined();
   int *conn=getNodalConnectivity()->getPointer();
   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
-  int nbOfCells=getNumberOfCells();
+  int nbOfCells(getNumberOfCells());
   for(int i=0;i<nbOfCells;i++)
     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
       {
index 38adadf3d9c88bae953a4b56c73c8457ffd0e863..e1b2c93d742da6149c3d72066243b5af65ebf97f 100644 (file)
@@ -140,7 +140,8 @@ 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<int,int>& newNodeNumbersO2N);
+    MEDCOUPLING_EXPORT void renumberNodesWithOffsetInConn(int offset);
+    MEDCOUPLING_EXPORT void renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& 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);
index 01bc5e64c46ef1852b9f157e81d4f1a1f2044a28..e4ddc68ec6ef4786363da79e7b60ca376c49325b 100644 (file)
@@ -1052,6 +1052,7 @@ namespace ParaMEDMEM
       virtual bool isEmptyMesh(const std::vector<int>& tinyInfo) const throw(INTERP_KERNEL::Exception);
       virtual MEDCouplingPointSet *deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception);
       virtual DataArrayDouble *getBoundingBoxForBBTree(double arcDetEps=1e-12) const throw(INTERP_KERNEL::Exception);
+      virtual void renumberNodesWithOffsetInConn(int offset) throw(INTERP_KERNEL::Exception);
       %extend 
          {
            std::string __str__() const throw(INTERP_KERNEL::Exception)
index 344f61447cdc6c7a4a73d86a8eb5d8a0ff0223a8..a140e971b6198ec746dbc0b94300d2c82a716d8e 100644 (file)
@@ -286,15 +286,13 @@ void MEDFileUMeshL2::loadPart(med_idt fid, int mId, const std::string& mName, co
   for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > >::const_iterator it0=_per_type_mesh.begin();it0!=_per_type_mesh.end();it0++)
     for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++)
       (*it1)->getMesh()->computeNodeIdsAlg(fetchedNodeIds);
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(DataArrayInt::BuildListOfSwitchedOn(fetchedNodeIds));
-  std::map<int,int> o2n;
-  int newId(0);
-  for(const int *it0=n2o->begin();it0!=n2o->end();it0++,newId++)
-    o2n[*it0]=newId;
+  int nMin(std::distance(fetchedNodeIds.begin(),std::find(fetchedNodeIds.begin(),fetchedNodeIds.end(),true)));
+  int nMax(std::distance(fetchedNodeIds.rbegin(),std::find(fetchedNodeIds.rbegin(),fetchedNodeIds.rend(),true)));
+  nMax=nCoords-nMax-1;
   for(std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> > >::const_iterator it0=_per_type_mesh.begin();it0!=_per_type_mesh.end();it0++)
     for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >::const_iterator it1=(*it0).begin();it1!=(*it0).end();it1++)
-      (*it1)->getMesh()->renumberNodesInConn(o2n);
-  loadPartCoords(fid,mId,infosOnComp,mName,dt,it,n2o);
+      (*it1)->getMesh()->renumberNodesWithOffsetInConn(-nMin);
+  loadPartCoords(fid,mId,infosOnComp,mName,dt,it,nMin,nMax);
 }
 
 void MEDFileUMeshL2::loadConnectivity(med_idt fid, int mdim, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
@@ -367,27 +365,22 @@ void MEDFileUMeshL2::loadCoords(med_idt fid, int mId, const std::vector<std::str
     _coords->setInfoOnComponent(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<std::string>& infosOnComp, const std::string& mName, int dt, int it, DataArrayInt *n2o)
+void MEDFileUMeshL2::loadPartCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const std::string& mName, int dt, int it, int nMin, int nMax)
 {
-  if(!n2o || !n2o->isAllocated() || n2o->getNumberOfComponents()!=1)
-    throw INTERP_KERNEL::Exception("MEDFileUMeshL2::loadPartCoords : n2o must be not NULL and allocated and with one component !");
   med_bool changement,transformation;
-  int spaceDim((int)infosOnComp.size()),nbNodesToLoad(n2o->getNumberOfTuples()),nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation));
+  int spaceDim((int)infosOnComp.size()),nCoords(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_COORDINATE,MED_NO_CMODE,&changement,&transformation));
   _coords=DataArrayDouble::New();
+  int nbNodesToLoad(nMax-nMin+1);
   _coords->alloc(nbNodesToLoad,spaceDim);
   med_filter filter=MED_FILTER_INIT,filter2=MED_FILTER_INIT;
-  n2o->applyLin(1,1);//C -> FORTRAN
-  MEDfilterEntityCr(fid,/*nentity*/nCoords,/*nvaluesperentity*/1,/*nconstituentpervalue*/spaceDim,
-                    /*constituentselect*/MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,
-                    /*profilename*/MED_NO_PROFILE,/*filterarraysize*/nbNodesToLoad,/*filterarray*/n2o->begin(),&filter);
+  MEDfilterBlockOfEntityCr(fid,/*nentity*/nCoords,/*nvaluesperentity*/1,/*nconstituentpervalue*/spaceDim,
+                           MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,MED_NO_PROFILE,
+                           /*start*/nMin+1,/*stride*/1,/*count*/1,/*blocksize*/nbNodesToLoad,
+                           /*lastblocksize=useless because count=1*/0,&filter);
   MEDmeshNodeCoordinateAdvancedRd(fid,mName.c_str(),dt,it,&filter,_coords->getPointer());
   MEDfilterClose(&filter);
-  MEDfilterEntityCr(fid,nCoords,1,1,MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,
-                    MED_NO_PROFILE,nbNodesToLoad,n2o->begin(),&filter2);
+  MEDfilterBlockOfEntityCr(fid,nCoords,1,1,MED_ALL_CONSTITUENT,MED_FULL_INTERLACE,MED_COMPACT_STMODE,
+                           MED_NO_PROFILE,nMin+1,1,1,nbNodesToLoad,0,&filter2);
   if(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NO_GEOTYPE,MED_FAMILY_NUMBER,MED_NODAL,&changement,&transformation)>0)
     {
       _fam_coords=DataArrayInt::New();
@@ -413,7 +406,6 @@ void MEDFileUMeshL2::loadPartCoords(med_idt fid, int mId, const std::vector<std:
     }
   else
     _name_coords=0;
-  n2o->applyLin(1,-1);//FORTRAN -> C
   MEDfilterClose(&filter2);
   _coords->setInfoOnComponents(infosOnComp);
 }
index d2863a5075c653f6b398efad85c93bce67fc1e58..8cdcc988f4f71817c2d045067d392c7d2de6e61f 100644 (file)
@@ -76,7 +76,7 @@ namespace ParaMEDMEM
     void loadConnectivity(med_idt fid, int mdim, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs);
     void loadPartOfConnectivity(med_idt fid, int mdim, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs);
     void loadCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const std::string& mName, int dt, int it);
-    void loadPartCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const std::string& mName, int dt, int it, DataArrayInt *n2o);
+    void loadPartCoords(med_idt fid, int mId, const std::vector<std::string>& infosOnComp, const std::string& mName, int dt, int it, int nMin, int nMax);
     int getNumberOfLevels() const { return _per_type_mesh.size(); }
     bool emptyLev(int levId) const { return _per_type_mesh[levId].empty(); }
     const std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshPerType> >& getLev(int levId) const { return _per_type_mesh[levId]; }