Salome HOME
#18963 Minimize compiler warnings
[plugins/netgenplugin.git] / src / NETGENPlugin / NETGENPlugin_NETGEN_3D.cxx
index 131c40a77b5eb175eb538b61a10e8c88e7bf8548..a3425b50609206dfb52f1ead47b98c3fcff3be66 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // 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.
+// 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
 #define OCCGEOMETRY
 #endif
 #include <occgeom.hpp>
+#include <ngexception.hpp>
 namespace nglib {
 #include <nglib.h>
 }
 namespace netgen {
+#ifdef NETGEN_V5
+  extern int OCCGenerateMesh (OCCGeometry&, Mesh*&, MeshingParameters&, int, int);
+#else
   extern int OCCGenerateMesh (OCCGeometry&, Mesh*&, int, int, char*);
+#endif
+
+  NETGENPLUGIN_DLL_HEADER
   extern MeshingParameters mparam;
+
+  NETGENPLUGIN_DLL_HEADER
   extern volatile multithreadt multithread;
 }
 using namespace nglib;
@@ -88,11 +97,9 @@ using namespace std;
  */
 //=============================================================================
 
-NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
-                             SMESH_Gen* gen)
-  : SMESH_3D_Algo(hypId, studyId, gen)
+NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, SMESH_Gen* gen)
+  : SMESH_3D_Algo(hypId, gen)
 {
-  MESSAGE("NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D");
   _name = "NETGEN_3D";
   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
   _compatibleHypothesis.push_back("MaxElementVolume");
@@ -116,7 +123,6 @@ NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
 
 NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D()
 {
-  MESSAGE("NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D");
 }
 
 //=============================================================================
@@ -129,15 +135,18 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis (SMESH_Mesh&         aMesh,
                                               const TopoDS_Shape& aShape,
                                               Hypothesis_Status&  aStatus)
 {
-  MESSAGE("NETGENPlugin_NETGEN_3D::CheckHypothesis");
-
   _hypMaxElementVolume = NULL;
   _hypParameters = NULL;
   _viscousLayersHyp = NULL;
   _maxElementVolume = DBL_MAX;
 
+  // for correct work of GetProgress():
+  netgen::multithread.percent = 0.;
+  netgen::multithread.task = "Volume meshing";
+  _progressByTic = -1.;
+
   list<const SMESHDS_Hypothesis*>::const_iterator itl;
-  const SMESHDS_Hypothesis* theHyp;
+  //const SMESHDS_Hypothesis* theHyp;
 
   const list<const SMESHDS_Hypothesis*>& hyps =
     GetUsedHypothesis(aMesh, aShape, /*ignoreAuxiliary=*/false);
@@ -153,18 +162,21 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis (SMESH_Mesh&         aMesh,
   {
     if ( !_hypMaxElementVolume )
       _hypMaxElementVolume = dynamic_cast< const StdMeshers_MaxElementVolume*> ( *h );
-    if ( !_viscousLayersHyp )
+    if ( !_viscousLayersHyp ) // several _viscousLayersHyp's allowed
       _viscousLayersHyp = dynamic_cast< const StdMeshers_ViscousLayers*> ( *h );
     if ( ! _hypParameters )
       _hypParameters = dynamic_cast< const NETGENPlugin_Hypothesis*> ( *h );
 
     if ( *h != _hypMaxElementVolume &&
          *h != _viscousLayersHyp &&
-         *h != _hypParameters)
+         *h != _hypParameters &&
+         !dynamic_cast< const StdMeshers_ViscousLayers*>(*h)) // several VL hyps allowed
       aStatus = HYP_INCOMPATIBLE;
   }
   if ( _hypMaxElementVolume && _hypParameters )
     aStatus = HYP_INCOMPATIBLE;
+  else if ( aStatus == HYP_OK && _viscousLayersHyp )
+    error( _viscousLayersHyp->CheckHypothesis( aMesh, aShape, aStatus ));
 
   if ( _hypMaxElementVolume )
     _maxElementVolume = _hypMaxElementVolume->GetMaxVolume();
@@ -181,19 +193,17 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis (SMESH_Mesh&         aMesh,
 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
                                      const TopoDS_Shape& aShape)
 {
-#ifdef WITH_SMESH_CANCEL_COMPUTE
   netgen::multithread.terminate = 0;
-#endif
-  MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
+  netgen::multithread.task = "Volume meshing";
+  _progressByTic = -1.;
 
   SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
 
   SMESH_MesherHelper helper(aMesh);
-  bool _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
+  _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
   helper.SetElementsOnShape( true );
 
-  int Netgen_NbOfNodes     = 0;
-
+  int Netgen_NbOfNodes = 0;
   double Netgen_point[3];
   int Netgen_triangle[3];
 
@@ -226,12 +236,14 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
     SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh ));
     if ( _viscousLayersHyp )
     {
+      netgen::multithread.percent = 3;
       proxyMesh = _viscousLayersHyp->Compute( aMesh, aShape );
       if ( !proxyMesh )
         return false;
     }
     if ( aMesh.NbQuadrangles() > 0 )
     {
+      netgen::multithread.percent = 6;
       StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
       Adaptor->Compute(aMesh,aShape,proxyMesh.get());
       proxyMesh.reset( Adaptor );
@@ -247,11 +259,21 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
            helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 )
         // IsReversedSubMesh() can work wrong on strongly curved faces,
         // so we use it as less as possible
-        isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
+        isRev = helper.IsReversedSubMesh( TopoDS::Face( aShapeFace ));
 
       const SMESHDS_SubMesh * aSubMeshDSFace = proxyMesh->GetSubMesh( aShapeFace );
       if ( !aSubMeshDSFace ) continue;
+
       SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
+      if ( _quadraticMesh &&
+           dynamic_cast< const SMESH_ProxyMesh::SubMesh*>( aSubMeshDSFace ))
+      {
+        // add medium nodes of proxy triangles to helper (#16843)
+        while ( iteratorElem->more() )
+          helper.AddTLinks( static_cast< const SMDS_MeshFace* >( iteratorElem->next() ));
+
+        iteratorElem = aSubMeshDSFace->GetElements();
+      }
       while ( iteratorElem->more() ) // loop on elements on a geom face
       {
         // check mesh face
@@ -325,9 +347,81 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
   // Generate the volume mesh
   // -------------------------
 
-  return compute( aMesh, helper, nodeVec, Netgen_mesh);
+  return ( ngLib._isComputeOk = compute( aMesh, helper, nodeVec, Netgen_mesh));
 }
 
+// namespace
+// {
+//   void limitVolumeSize( netgen::Mesh* ngMesh,
+//                         double        maxh )
+//   {
+//     // get average h of faces
+//     double faceh = 0;
+//     int nbh = 0;
+//     for (int i = 1; i <= ngMesh->GetNSE(); i++)
+//     {
+//       const netgen::Element2d& face = ngMesh->SurfaceElement(i);
+//       for (int j=1; j <= face.GetNP(); ++j)
+//       {
+//         const netgen::PointIndex & i1 = face.PNumMod(j);
+//         const netgen::PointIndex & i2 = face.PNumMod(j+1);
+//         if ( i1 < i2 )
+//         {
+//           const netgen::Point3d & p1 = ngMesh->Point( i1 );
+//           const netgen::Point3d & p2 = ngMesh->Point( i2 );
+//           faceh += netgen::Dist2( p1, p2 );
+//           nbh++;
+//         }
+//       }
+//     }
+//     faceh = Sqrt( faceh / nbh );
+
+//     double compareh;
+//     if      ( faceh < 0.5 * maxh ) compareh = -1;
+//     else if ( faceh > 1.5 * maxh ) compareh = 1;
+//     else                           compareh = 0;
+//     // cerr << "faceh " << faceh << endl;
+//     // cerr << "init maxh " << maxh << endl;
+//     // cerr << "compareh " << compareh << endl;
+
+//     if ( compareh > 0 )
+//       maxh *= 1.2;
+//     else
+//       maxh *= 0.8;
+//     // cerr << "maxh " << maxh << endl;
+
+//     // get bnd box
+//     netgen::Point3d pmin, pmax;
+//     ngMesh->GetBox( pmin, pmax, 0 );
+//     const double dx = pmax.X() - pmin.X();
+//     const double dy = pmax.Y() - pmin.Y();
+//     const double dz = pmax.Z() - pmin.Z();
+
+//     if ( ! & ngMesh->LocalHFunction() )
+//       ngMesh->SetLocalH( pmin, pmax, compareh <= 0 ? 0.1 : 0.5 );
+
+//     // adjusted by SALOME_TESTS/Grids/smesh/bugs_08/I8
+//     const int nbX = Max( 2, int( dx / maxh * 2 ));
+//     const int nbY = Max( 2, int( dy / maxh * 2 ));
+//     const int nbZ = Max( 2, int( dz / maxh * 2 ));
+
+//     netgen::Point3d p;
+//     for ( int i = 0; i <= nbX; ++i )
+//     {
+//       p.X() = pmin.X() +  i * dx / nbX;
+//       for ( int j = 0; j <= nbY; ++j )
+//       {
+//         p.Y() = pmin.Y() +  j * dy / nbY;
+//         for ( int k = 0; k <= nbZ; ++k )
+//         {
+//           p.Z() = pmin.Z() +  k * dz / nbZ;
+//           ngMesh->RestrictLocalH( p, maxh );
+//         }
+//       }
+//     }
+//   }
+// }
+
 //================================================================================
 /*!
  * \brief set parameters and generate the volume mesh
@@ -339,29 +433,49 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
                                      vector< const SMDS_MeshNode* >& nodeVec,
                                      Ng_Mesh *                       Netgen_mesh)
 {
-#ifdef WITH_SMESH_CANCEL_COMPUTE
   netgen::multithread.terminate = 0;
-#endif
+
   netgen::Mesh* ngMesh = (netgen::Mesh*)Netgen_mesh;
   int Netgen_NbOfNodes = Ng_GetNP(Netgen_mesh);
 
+#ifndef NETGEN_V5
   char *optstr = 0;
+#endif
   int startWith = netgen::MESHCONST_MESHVOLUME;
   int endWith   = netgen::MESHCONST_OPTVOLUME;
   int err = 1;
 
   NETGENPlugin_Mesher aMesher( &aMesh, helper.GetSubShape(), /*isVolume=*/true );
   netgen::OCCGeometry occgeo;
-  
+
   if ( _hypParameters )
   {
     aMesher.SetParameters( _hypParameters );
+
+    if ( !_hypParameters->GetLocalSizesAndEntries().empty() ||
+         !_hypParameters->GetMeshSizeFile().empty() )
+    {
+      if ( ! &ngMesh->LocalHFunction() )
+      {
+        netgen::Point3d pmin, pmax;
+        ngMesh->GetBox( pmin, pmax, 0 );
+        ngMesh->SetLocalH( pmin, pmax, _hypParameters->GetGrowthRate() );
+      }
+      aMesher.SetLocalSize( occgeo, *ngMesh );
+
+      try {
+        ngMesh->LoadLocalMeshSize( netgen::mparam.meshsizefilename );
+      } catch (netgen::NgException & ex) {
+        return error( COMPERR_BAD_PARMETERS, ex.What() );
+      }
+    }
     if ( !_hypParameters->GetOptimize() )
       endWith = netgen::MESHCONST_MESHVOLUME;
   }
   else if ( _hypMaxElementVolume )
   {
     netgen::mparam.maxh = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );
+    // limitVolumeSize( ngMesh, netgen::mparam.maxh ); // result is unpredictable
   }
   else if ( aMesh.HasShapeToMesh() )
   {
@@ -382,15 +496,17 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
 
   try
   {
-#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
     OCC_CATCH_SIGNALS;
-#endif
+
+#ifdef NETGEN_V5
+    ngMesh->CalcLocalH(netgen::mparam.grading);
+    err = netgen::OCCGenerateMesh(occgeo, ngMesh, netgen::mparam, startWith, endWith);
+#else
     ngMesh->CalcLocalH();
     err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr);
-#ifdef WITH_SMESH_CANCEL_COMPUTE
+#endif
     if(netgen::multithread.terminate)
       return false;
-#endif
     if ( err )
       error(SMESH_Comment("Error in netgen::OCCGenerateMesh() at ") << netgen::multithread.task);
   }
@@ -403,20 +519,25 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
       str << ": " << ex.GetMessageString();
     error(str);
   }
+  catch (netgen::NgException& exc)
+  {
+    SMESH_Comment str("NgException");
+    if ( strlen( netgen::multithread.task ) > 0 )
+      str << " at " << netgen::multithread.task;
+    str << ": " << exc.What();
+    error(str);
+  }
   catch (...)
   {
     SMESH_Comment str("Exception in  netgen::OCCGenerateMesh()");
-    str << " at " << netgen::multithread.task;
+    if ( strlen( netgen::multithread.task ) > 0 )
+      str << " at " << netgen::multithread.task;
     error(str);
   }
 
   int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
   int Netgen_NbOfTetra    = Ng_GetNE(Netgen_mesh);
 
-  MESSAGE("End of Volume Mesh Generation. err=" << err <<
-          ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
-          ", nb tetra: " << Netgen_NbOfTetra);
-
   // -------------------------------------------------------------------
   // Feed back the SMESHDS with the generated Nodes and Volume Elements
   // -------------------------------------------------------------------
@@ -424,7 +545,7 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
   if ( err )
   {
     SMESH_ComputeErrorPtr ce = NETGENPlugin_Mesher::ReadErrors(nodeVec);
-    if ( ce && !ce->myBadElements.empty() )
+    if ( ce && ce->HasBadElems() )
       error( ce );
   }
 
@@ -472,30 +593,25 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
                                      SMESH_MesherHelper* aHelper)
 {
-  MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);  
   const int invalid_ID = -1;
-  bool _quadraticMesh = false;
 
-  SMESH_MesherHelper::MType MeshType = aHelper->IsQuadraticMesh();
+  netgen::multithread.terminate = 0;
+  _progressByTic = -1.;
 
-  if(MeshType == SMESH_MesherHelper::COMP)
+  SMESH_MesherHelper::MType MeshType = aHelper->IsQuadraticMesh();
+  if ( MeshType == SMESH_MesherHelper::COMP )
     return error( COMPERR_BAD_INPUT_MESH,
-                  SMESH_Comment("Mesh with linear and quadratic elements given."));
-  else if (MeshType == SMESH_MesherHelper::QUADRATIC)
-    _quadraticMesh = true;
+                  SMESH_Comment("Mesh with linear and quadratic elements given"));
+
+  aHelper->SetIsQuadratic( MeshType == SMESH_MesherHelper::QUADRATIC );
 
   // ---------------------------------
   // Feed the Netgen with surface mesh
   // ---------------------------------
 
   int Netgen_NbOfNodes = 0;
-  int Netgen_param2ndOrder = 0;
-  double Netgen_paramFine = 1.;
-  double Netgen_paramSize = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );
-  
   double Netgen_point[3];
   int Netgen_triangle[3];
-  int Netgen_tetrahedron[4];
 
   NETGENPlugin_NetgenLibWrapper ngLib;
   Ng_Mesh * Netgen_mesh = ngLib._ngMesh;
@@ -506,6 +622,13 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
     StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
     Adaptor->Compute(aMesh);
     proxyMesh.reset( Adaptor );
+
+    if ( aHelper->IsQuadraticMesh() )
+    {
+      SMDS_ElemIteratorPtr fIt = proxyMesh->GetFaces();
+      while( fIt->more())
+        aHelper->AddTLinks( static_cast< const SMDS_MeshFace* >( fIt->next() ));
+    }
   }
 
   // maps nodes to ng ID
@@ -554,16 +677,45 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
   // Generate the volume mesh
   // -------------------------
 
-  return compute( aMesh, *aHelper, nodeVec, Netgen_mesh);
+  return ( ngLib._isComputeOk = compute( aMesh, *aHelper, nodeVec, Netgen_mesh));
 }
 
-#ifdef WITH_SMESH_CANCEL_COMPUTE
 void NETGENPlugin_NETGEN_3D::CancelCompute()
 {
   SMESH_Algo::CancelCompute();
   netgen::multithread.terminate = 1;
 }
-#endif
+
+//================================================================================
+/*!
+ * \brief Return Compute progress
+ */
+//================================================================================
+
+double NETGENPlugin_NETGEN_3D::GetProgress() const
+{
+  double res;
+  const char* volMeshing = "Volume meshing";
+  const char* dlnMeshing = "Delaunay meshing";
+  const double meshingRatio = 0.15;
+  const_cast<NETGENPlugin_NETGEN_3D*>( this )->_progressTic++;
+
+  if ( _progressByTic < 0. &&
+       ( strncmp( netgen::multithread.task, dlnMeshing, 3 ) == 0 ||
+         strncmp( netgen::multithread.task, volMeshing, 3 ) == 0 ))
+  {
+    res = 0.001 + meshingRatio * netgen::multithread.percent / 100.;
+    //cout << netgen::multithread.task << " " <<_progressTic << "-" << netgen::multithread.percent << endl;
+  }
+  else // different otimizations
+  {
+    if ( _progressByTic < 0. )
+      ((NETGENPlugin_NETGEN_3D*)this)->_progressByTic = meshingRatio / _progressTic;
+    res = _progressByTic * _progressTic;
+    //cout << netgen::multithread.task << " " << _progressTic << " " << res << endl;
+  }
+  return Min ( res, 0.98 );
+}
 
 //=============================================================================
 /*!