Salome HOME
0052673: Viscous Layers hypothesis is not taken into account by NETGEN 3D algo
[plugins/netgenplugin.git] / src / NETGENPlugin / NETGENPlugin_NETGEN_3D.cxx
index cc05f2a40cf37cba476693654e6fb7363794122f..b16e00b13a8e09fac70ec35913a74c249aefab1c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  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
@@ -140,6 +140,11 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis (SMESH_Mesh&         aMesh,
   _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;
 
@@ -157,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();
@@ -186,6 +194,8 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
                                      const TopoDS_Shape& aShape)
 {
   netgen::multithread.terminate = 0;
+  netgen::multithread.task = "Volume meshing";
+  _progressByTic = -1.;
 
   SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
 
@@ -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 );
@@ -328,6 +340,78 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
   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
@@ -363,6 +447,7 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
   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() )
   {
@@ -383,9 +468,8 @@ 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);
@@ -487,6 +571,9 @@ bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
 {
   const int invalid_ID = -1;
 
+  netgen::multithread.terminate = 0;
+  _progressByTic = -1.;
+
   SMESH_MesherHelper::MType MeshType = aHelper->IsQuadraticMesh();
   if ( MeshType == SMESH_MesherHelper::COMP )
     return error( COMPERR_BAD_INPUT_MESH,
@@ -573,6 +660,37 @@ void NETGENPlugin_NETGEN_3D::CancelCompute()
   netgen::multithread.terminate = 1;
 }
 
+//================================================================================
+/*!
+ * \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 );
+}
+
 //=============================================================================
 /*!
  *