Salome HOME
#18963 Minimize compiler warnings
[modules/smesh.git] / src / StdMeshers / StdMeshers_ViscousLayers.cxx
index 075d1b46d68c1f32faaff7fac158250546923410..822f1742c1910d5998d54c606851e10b965bc5aa 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -206,8 +206,8 @@ namespace VISCOUS_3D
     virtual void ProcessEvent(const int                       event,
                               const int                       eventType,
                               SMESH_subMesh*                  subMesh,
-                              SMESH_subMeshEventListenerData* data,
-                              const SMESH_Hypothesis*         hyp)
+                              SMESH_subMeshEventListenerData* /*data*/,
+                              const SMESH_Hypothesis*         /*hyp*/)
     {
       if (( SMESH_subMesh::COMPUTE_EVENT       == eventType ) &&
           ( SMESH_subMesh::CHECK_COMPUTE_STATE != event &&
@@ -612,12 +612,16 @@ namespace VISCOUS_3D
         _thickness      = Max( _thickness, hyp->GetTotalThickness() );
         _stretchFactor += hyp->GetStretchFactor();
         _method         = hyp->GetMethod();
+        if ( _groupName.empty() )
+          _groupName = hyp->GetGroupName();
       }
     }
     double GetTotalThickness() const { return _thickness; /*_nbHyps ? _thickness / _nbHyps : 0;*/ }
     double GetStretchFactor()  const { return _nbHyps ? _stretchFactor / _nbHyps : 0; }
     int    GetNumberLayers()   const { return _nbLayers; }
     int    GetMethod()         const { return _method; }
+    bool   ToCreateGroup()     const { return !_groupName.empty(); }
+    const std::string& GetGroupName() const { return _groupName; }
 
     bool   UseSurfaceNormal()  const
     { return _method == StdMeshers_ViscousLayers::SURF_OFFSET_SMOOTH; }
@@ -636,8 +640,9 @@ namespace VISCOUS_3D
     static bool Equals( double v1, double v2 ) { return Abs( v1 - v2 ) < 0.01 * ( v1 + v2 ); }
 
   private:
-    int     _nbLayers, _nbHyps, _method;
-    double  _thickness, _stretchFactor;
+    int         _nbLayers, _nbHyps, _method;
+    double      _thickness, _stretchFactor;
+    std::string _groupName;
   };
 
   //--------------------------------------------------------------------------------
@@ -912,7 +917,7 @@ namespace VISCOUS_3D
 
   private:
 
-    bool findSolidsWithLayers();
+    bool findSolidsWithLayers(const bool checkFaceMesh=true);
     bool setBefore( _SolidData& solidBefore, _SolidData& solidAfter );
     bool findFacesWithLayers(const bool onlyWith=false);
     void findPeriodicFaces();
@@ -1086,7 +1091,7 @@ namespace VISCOUS_3D
                              Handle(ShapeAnalysis_Surface)& surface,
                              const TopoDS_Face&             F,
                              SMESH_MesherHelper&            helper);
-    bool smoothComplexEdge( _SolidData&                    data,
+    bool smoothComplexEdge( _SolidData&                     data,
                             Handle(ShapeAnalysis_Surface)& surface,
                             const TopoDS_Face&             F,
                             SMESH_MesherHelper&            helper);
@@ -1247,7 +1252,8 @@ namespace VISCOUS_3D
 StdMeshers_ViscousLayers::StdMeshers_ViscousLayers(int hypId, SMESH_Gen* gen)
   :SMESH_Hypothesis(hypId, gen),
    _isToIgnoreShapes(1), _nbLayers(1), _thickness(1), _stretchFactor(1),
-   _method( SURF_OFFSET_SMOOTH )
+   _method( SURF_OFFSET_SMOOTH ),
+   _groupName("")
 {
   _name = StdMeshers_ViscousLayers::GetHypType();
   _param_algo_dim = -3; // auxiliary hyp used by 3D algos
@@ -1279,6 +1285,15 @@ void StdMeshers_ViscousLayers::SetMethod( ExtrusionMethod method )
   if ( _method != method )
     _method = method, NotifySubMeshesHypothesisModification();
 } // --------------------------------------------------------------------------------
+void StdMeshers_ViscousLayers::SetGroupName(const std::string& name)
+{
+  if ( _groupName != name )
+  {
+    _groupName = name;
+    if ( !_groupName.empty() )
+      NotifySubMeshesHypothesisModification();
+  }
+} // --------------------------------------------------------------------------------
 SMESH_ProxyMesh::Ptr
 StdMeshers_ViscousLayers::Compute(SMESH_Mesh&         theMesh,
                                   const TopoDS_Shape& theShape,
@@ -1333,6 +1348,9 @@ std::ostream & StdMeshers_ViscousLayers::SaveTo(std::ostream & save)
     save << " " << _shapeIds[i];
   save << " " << !_isToIgnoreShapes; // negate to keep the behavior in old studies.
   save << " " << _method;
+  save << " " << _groupName.size();
+  if ( !_groupName.empty() )
+    save << " " << _groupName;
   return save;
 } // --------------------------------------------------------------------------------
 std::istream & StdMeshers_ViscousLayers::LoadFrom(std::istream & load)
@@ -1345,14 +1363,21 @@ std::istream & StdMeshers_ViscousLayers::LoadFrom(std::istream & load)
     _isToIgnoreShapes = !shapeToTreat;
     if ( load >> method )
       _method = (ExtrusionMethod) method;
+    int nameSize = 0;
+    if ( load >> nameSize && nameSize > 0 )
+    {
+      _groupName.resize( nameSize );
+      load.get( _groupName[0] ); // remove a white-space
+      load.getline( &_groupName[0], nameSize + 1 );
+    }
   }
   else {
     _isToIgnoreShapes = true; // old behavior
   }
   return load;
 } // --------------------------------------------------------------------------------
-bool StdMeshers_ViscousLayers::SetParametersByMesh(const SMESH_Mesh*   theMesh,
-                                                   const TopoDS_Shape& theShape)
+bool StdMeshers_ViscousLayers::SetParametersByMesh(const SMESH_Mesh*   /*theMesh*/,
+                                                   const TopoDS_Shape& /*theShape*/)
 {
   // TODO
   return false;
@@ -1378,6 +1403,36 @@ bool StdMeshers_ViscousLayers::IsShapeWithLayers(int shapeIndex) const
     ( std::find( _shapeIds.begin(), _shapeIds.end(), shapeIndex ) != _shapeIds.end() );
   return IsToIgnoreShapes() ? !isIn : isIn;
 }
+
+// --------------------------------------------------------------------------------
+SMDS_MeshGroup* StdMeshers_ViscousLayers::CreateGroup( const std::string&  theName,
+                                                       SMESH_Mesh&         theMesh,
+                                                       SMDSAbs_ElementType theType)
+{
+  SMESH_Group*      group = 0;
+  SMDS_MeshGroup* groupDS = 0;
+
+  if ( theName.empty() )
+    return groupDS;
+       
+  if ( SMESH_Mesh::GroupIteratorPtr grIt = theMesh.GetGroups() )
+    while( grIt->more() && !group )
+    {
+      group = grIt->next();
+      if ( !group ||
+           group->GetGroupDS()->GetType() != theType ||
+           group->GetName()               != theName ||
+           !dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() ))
+        group = 0;
+    }
+  if ( !group )
+    group = theMesh.AddGroup( theType, theName.c_str() );
+
+  groupDS = & dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() )->SMDSGroup();
+
+  return groupDS;
+}
+
 // END StdMeshers_ViscousLayers hypothesis
 //================================================================================
 
@@ -1716,7 +1771,7 @@ namespace VISCOUS_3D
     PyDump(SMESH_Mesh& m) {
       int tag = 3 + m.GetId();
       const char* fname = "/tmp/viscous.py";
-      cout << "execfile('"<<fname<<"')"<<endl;
+      cout << "exec(open('"<<fname<<"','rb').read() )"<<endl;
       py = _pyStream = new ofstream(fname);
       *py << "import SMESH" << endl
           << "from salome.smesh import smeshBuilder" << endl
@@ -1985,7 +2040,7 @@ SMESH_ComputeErrorPtr _ViscousBuilder::CheckHypotheses( SMESH_Mesh&         mesh
     return SMESH_ComputeErrorPtr(); // everything already computed
 
 
-  findSolidsWithLayers();
+  findSolidsWithLayers( /*checkFaceMesh=*/false );
   bool ok = findFacesWithLayers( true );
 
   // remove _MeshOfSolid's of _SolidData's
@@ -2004,7 +2059,7 @@ SMESH_ComputeErrorPtr _ViscousBuilder::CheckHypotheses( SMESH_Mesh&         mesh
  */
 //================================================================================
 
-bool _ViscousBuilder::findSolidsWithLayers()
+bool _ViscousBuilder::findSolidsWithLayers(const bool checkFaceMesh)
 {
   // get all solids
   TopTools_IndexedMapOfShape allSolids;
@@ -2014,13 +2069,28 @@ bool _ViscousBuilder::findSolidsWithLayers()
   SMESH_HypoFilter filter;
   for ( int i = 1; i <= allSolids.Extent(); ++i )
   {
-    // find StdMeshers_ViscousLayers hyp assigned to the i-th solid
     SMESH_subMesh* sm = _mesh->GetSubMesh( allSolids(i) );
     if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->NbElements() > 0 )
       continue; // solid is already meshed
+    // TODO: check if algo is hidden
     SMESH_Algo* algo = sm->GetAlgo();
     if ( !algo ) continue;
-    // TODO: check if algo is hidden
+    // check if all FACEs are meshed, which can be false if Compute() a sub-shape
+    if ( checkFaceMesh )
+    {
+      bool facesMeshed = true;
+      SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,true);
+      while ( smIt->more() && facesMeshed )
+      {
+        SMESH_subMesh * faceSM = smIt->next();
+        if ( faceSM->GetSubShape().ShapeType() != TopAbs_FACE )
+          break;
+        facesMeshed = faceSM->IsMeshComputed();
+      }
+      if ( !facesMeshed )
+        continue;
+    }
+    // find StdMeshers_ViscousLayers hyp assigned to the i-th solid
     const list <const SMESHDS_Hypothesis *> & allHyps =
       algo->GetUsedHypothesis(*_mesh, allSolids(i), /*ignoreAuxiliary=*/false);
     _SolidData* soData = 0;
@@ -3249,12 +3319,22 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data )
           if ( isC1 )
           {
             double maxEdgeLen = 3 * Min( eov._edges[0]->_maxLen, eov._hyp.GetTotalThickness() );
-            double eLen1 = SMESH_Algo::EdgeLength( TopoDS::Edge( dirOfEdges[i].first->_shape ));
-            double eLen2 = SMESH_Algo::EdgeLength( TopoDS::Edge( dirOfEdges[j].first->_shape ));
-            if ( eLen1 < maxEdgeLen ) eov._eosC1.push_back( dirOfEdges[i].first );
-            if ( eLen2 < maxEdgeLen ) eov._eosC1.push_back( dirOfEdges[j].first );
-            dirOfEdges[i].first = 0;
-            dirOfEdges[j].first = 0;
+            for ( int isJ = 0; isJ < 2; ++isJ ) // loop on [i,j]
+            {
+              size_t k = isJ ? j : i;
+              const TopoDS_Edge& e = TopoDS::Edge( dirOfEdges[k].first->_shape );
+              double eLen = SMESH_Algo::EdgeLength( e );
+              if ( eLen < maxEdgeLen )
+              {
+                TopoDS_Shape oppV = SMESH_MesherHelper::IthVertex( 0, e );
+                if ( oppV.IsSame( V ))
+                  oppV = SMESH_MesherHelper::IthVertex( 1, e );
+                _EdgesOnShape* eovOpp = data.GetShapeEdges( oppV );
+                if ( dirOfEdges[k].second * eovOpp->_edges[0]->_normal < 0 )
+                  eov._eosC1.push_back( dirOfEdges[k].first );
+              }
+              dirOfEdges[k].first = 0;
+            }
           }
         }
   } // fill _eosC1 of VERTEXes
@@ -3873,7 +3953,7 @@ gp_XYZ _ViscousBuilder::getFaceNormal(const SMDS_MeshNode* node,
 
 bool _ViscousBuilder::getFaceNormalAtSingularity( const gp_XY&        uv,
                                                   const TopoDS_Face&  face,
-                                                  SMESH_MesherHelper& helper,
+                                                  SMESH_MesherHelper& /*helper*/,
                                                   gp_Dir&             normal )
 {
   BRepAdaptor_Surface surface( face );
@@ -5232,7 +5312,9 @@ bool _ViscousBuilder::smoothAndCheck(_SolidData& data,
   } // loop on data._edgesOnShape
 
   if ( !is1stBlocked )
+  {
     dumpFunctionEnd();
+  }
 
   if ( closestFace && le )
   {
@@ -5445,7 +5527,7 @@ void _ViscousBuilder::makeOffsetSurface( _EdgesOnShape& eos, SMESH_MesherHelper&
 
     eos._offsetSurf = new ShapeAnalysis_Surface( surf );
   }
-  catch ( Standard_Failure )
+  catch ( Standard_Failure& )
   {
   }
 }
@@ -5547,8 +5629,9 @@ void _ViscousBuilder::putOnOffsetSurface( _EdgesOnShape&            eos,
                  << "_InfStep" << infStep << "_" << smooStep );
     for ( ; i < eos._edges.size(); ++i )
     {
-      if ( eos._edges[i]->Is( _LayerEdge::MARKED ))
+      if ( eos._edges[i]->Is( _LayerEdge::MARKED )) {
         dumpMove( eos._edges[i]->_nodes.back() );
+      }
     }
     dumpFunctionEnd();
   }
@@ -6006,10 +6089,10 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData&                    data,
  */
 //================================================================================
 
-bool _Smoother1D::smoothComplexEdge( _SolidData&                    data,
+bool _Smoother1D::smoothComplexEdge( _SolidData&                    /*data*/,
                                      Handle(ShapeAnalysis_Surface)& surface,
                                      const TopoDS_Face&             F,
-                                     SMESH_MesherHelper&            helper)
+                                     SMESH_MesherHelper&            /*helper*/)
 {
   if ( _offPoints.empty() )
     return false;
@@ -6397,7 +6480,7 @@ gp_XYZ _Smoother1D::getNormalNormal( const gp_XYZ & normal,
 void _Smoother1D::offPointsToPython() const
 {
   const char* fname = "/tmp/offPoints.py";
-  cout << "execfile('"<<fname<<"')"<<endl;
+  cout << "exec(open('"<<fname<<"','rb').read() )"<<endl;
   ofstream py(fname);
   py << "import SMESH" << endl
      << "from salome.smesh import smeshBuilder" << endl
@@ -6666,7 +6749,7 @@ void _SolidData::AddShapesToSmooth( const set< _EdgesOnShape* >& eosToSmooth,
  */
 //================================================================================
 
-void _ViscousBuilder::limitMaxLenByCurvature( _SolidData& data, SMESH_MesherHelper& helper )
+void _ViscousBuilder::limitMaxLenByCurvature( _SolidData& data, SMESH_MesherHelper& /*helper*/ )
 {
   // find intersection of neighbor _LayerEdge's to limit _maxLen
   // according to local curvature (IPAL52648)
@@ -6718,9 +6801,9 @@ void _ViscousBuilder::limitMaxLenByCurvature( _SolidData& data, SMESH_MesherHelp
 
 void _ViscousBuilder::limitMaxLenByCurvature( _LayerEdge*    e1,
                                               _LayerEdge*    e2,
-                                              _EdgesOnShape& eos1,
-                                              _EdgesOnShape& eos2,
-                                              const bool     isSmoothable )
+                                              _EdgesOnShape& /*eos1*/,
+                                              _EdgesOnShape& /*eos2*/,
+                                              const bool     /*isSmoothable*/ )
 {
   if (( e1->_nodes[0]->GetPosition()->GetDim() !=
         e2->_nodes[0]->GetPosition()->GetDim() ) &&
@@ -7039,7 +7122,7 @@ void _ViscousBuilder::findEdgesToUpdateNormalNearConvexFace( _ConvexFace &
 bool _ViscousBuilder::updateNormals( _SolidData&         data,
                                      SMESH_MesherHelper& helper,
                                      int                 stepNb,
-                                     double              stepSize)
+                                     double              /*stepSize*/)
 {
   updateNormalsOfC1Vertices( data );
 
@@ -7204,7 +7287,7 @@ bool _ViscousBuilder::updateNormals( _SolidData&         data,
       _LayerEdge*    edge = e2neIt->first;
       _LayerEdge& newEdge = e2neIt->second;
       _EdgesOnShape*  eos = data.GetShapeEdges( edge );
-      if ( edge->Is( _LayerEdge::BLOCKED && newEdge._maxLen > edge->_len ))
+      if ( edge->Is( _LayerEdge::BLOCKED ) && newEdge._maxLen > edge->_len )
         continue;
 
       // Check if a new _normal is OK:
@@ -7379,7 +7462,7 @@ bool _ViscousBuilder::isNewNormalOk( _SolidData&   data,
 //================================================================================
 
 bool _ViscousBuilder::updateNormalsOfSmoothed( _SolidData&         data,
-                                               SMESH_MesherHelper& helper,
+                                               SMESH_MesherHelper& /*helper*/,
                                                const int           nbSteps,
                                                const double        stepSize )
 {
@@ -8837,7 +8920,7 @@ int _LayerEdge::Smooth(const int step, const bool isConcaveFace, bool findBest )
 //================================================================================
 
 void _LayerEdge::ChooseSmooFunction( const set< TGeomID >& concaveVertices,
-                                     const TNode2Edge&     n2eMap)
+                                     const TNode2Edge&     /*n2eMap*/)
 {
   if ( _smooFunction ) return;
 
@@ -9030,7 +9113,7 @@ gp_XYZ _LayerEdge::smoothAngular()
       else
         norm += cross;
     }
-    catch (Standard_Failure) { // if |cross| == 0.
+    catch (Standard_Failure&) { // if |cross| == 0.
     }
   }
   gp_XYZ vec = newPos - pN;
@@ -10230,6 +10313,11 @@ bool _ViscousBuilder::refine(_SolidData& data)
     const TGeomID faceID = getMeshDS()->ShapeToIndex( exp.Current() );
     if ( data._ignoreFaceIds.count( faceID ))
       continue;
+    _EdgesOnShape*    eos = data.GetShapeEdges( faceID );
+    SMDS_MeshGroup* group = StdMeshers_ViscousLayers::CreateGroup( eos->_hyp.GetGroupName(),
+                                                                   *helper.GetMesh(),
+                                                                   SMDSAbs_Volume );
+    std::vector< const SMDS_MeshElement* > vols;
     const bool isReversedFace = data._reversedFaceIds.count( faceID );
     SMESHDS_SubMesh*    fSubM = getMeshDS()->MeshElements( exp.Current() );
     SMDS_ElemIteratorPtr  fIt = fSubM->GetElements();
@@ -10260,14 +10348,20 @@ bool _ViscousBuilder::refine(_SolidData& data)
       if ( 0 < nnSet.size() && nnSet.size() < 3 )
         continue;
 
+      vols.clear();
+      const SMDS_MeshElement* vol;
+
       switch ( nbNodes )
       {
       case 3: // TRIA
       {
         // PENTA
         for ( size_t iZ = 1; iZ < minZ; ++iZ )
-          helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
-                            (*nnVec[0])[iZ],   (*nnVec[1])[iZ],   (*nnVec[2])[iZ]);
+        {
+          vol = helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1], (*nnVec[2])[iZ-1],
+                                  (*nnVec[0])[iZ],   (*nnVec[1])[iZ],   (*nnVec[2])[iZ]);
+          vols.push_back( vol );
+        }
 
         for ( size_t iZ = minZ; iZ < maxZ; ++iZ )
         {
@@ -10280,16 +10374,18 @@ bool _ViscousBuilder::refine(_SolidData& data)
             int i2 = *degenEdgeInd.begin();
             int i0 = helper.WrapIndex( i2 - 1, nbNodes );
             int i1 = helper.WrapIndex( i2 + 1, nbNodes );
-            helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
-                              (*nnVec[i1])[iZ  ], (*nnVec[i0])[iZ  ], (*nnVec[i2]).back());
+            vol = helper.AddVolume( (*nnVec[i0])[iZ-1], (*nnVec[i1])[iZ-1],
+                                    (*nnVec[i1])[iZ  ], (*nnVec[i0])[iZ  ], (*nnVec[i2]).back());
+            vols.push_back( vol );
           }
           else  // TETRA
           {
             int i3 = !degenEdgeInd.count(0) ? 0 : !degenEdgeInd.count(1) ? 1 : 2;
-            helper.AddVolume( (*nnVec[  0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ],
-                              (*nnVec[  1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ],
-                              (*nnVec[  2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ],
-                              (*nnVec[ i3 ])[ iZ ]);
+            vol = helper.AddVolume( (*nnVec[  0 ])[ i3 == 0 ? iZ-1 : nnVec[0]->size()-1 ],
+                                    (*nnVec[  1 ])[ i3 == 1 ? iZ-1 : nnVec[1]->size()-1 ],
+                                    (*nnVec[  2 ])[ i3 == 2 ? iZ-1 : nnVec[2]->size()-1 ],
+                                    (*nnVec[ i3 ])[ iZ ]);
+            vols.push_back( vol );
           }
         }
         break; // TRIA
@@ -10298,10 +10394,13 @@ bool _ViscousBuilder::refine(_SolidData& data)
       {
         // HEX
         for ( size_t iZ = 1; iZ < minZ; ++iZ )
-          helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
-                            (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
-                            (*nnVec[0])[iZ],   (*nnVec[1])[iZ],
-                            (*nnVec[2])[iZ],   (*nnVec[3])[iZ]);
+        {
+          vol = helper.AddVolume( (*nnVec[0])[iZ-1], (*nnVec[1])[iZ-1],
+                                  (*nnVec[2])[iZ-1], (*nnVec[3])[iZ-1],
+                                  (*nnVec[0])[iZ],   (*nnVec[1])[iZ],
+                                  (*nnVec[2])[iZ],   (*nnVec[3])[iZ]);
+          vols.push_back( vol );
+        }
 
         for ( size_t iZ = minZ; iZ < maxZ; ++iZ )
         {
@@ -10320,9 +10419,9 @@ bool _ViscousBuilder::refine(_SolidData& data)
             int i0 = helper.WrapIndex( i3 + 1, nbNodes );
             int i1 = helper.WrapIndex( i0 + 1, nbNodes );
 
-            const SMDS_MeshElement* vol =
-              helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
-                                nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+            vol = helper.AddVolume( nnVec[i3]->back(), (*nnVec[i0])[iZ], (*nnVec[i0])[iZ-1],
+                                    nnVec[i2]->back(), (*nnVec[i1])[iZ], (*nnVec[i1])[iZ-1]);
+            vols.push_back( vol );
             if ( !ok && vol )
               degenVols.push_back( vol );
           }
@@ -10330,15 +10429,15 @@ bool _ViscousBuilder::refine(_SolidData& data)
 
           default: // degen HEX
           {
-            const SMDS_MeshElement* vol =
-              helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(),
-                                nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(),
-                                nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(),
-                                nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(),
-                                nnVec[0]->size() > iZ   ? (*nnVec[0])[iZ]   : nnVec[0]->back(),
-                                nnVec[1]->size() > iZ   ? (*nnVec[1])[iZ]   : nnVec[1]->back(),
-                                nnVec[2]->size() > iZ   ? (*nnVec[2])[iZ]   : nnVec[2]->back(),
-                                nnVec[3]->size() > iZ   ? (*nnVec[3])[iZ]   : nnVec[3]->back());
+            vol = helper.AddVolume( nnVec[0]->size() > iZ-1 ? (*nnVec[0])[iZ-1] : nnVec[0]->back(),
+                                    nnVec[1]->size() > iZ-1 ? (*nnVec[1])[iZ-1] : nnVec[1]->back(),
+                                    nnVec[2]->size() > iZ-1 ? (*nnVec[2])[iZ-1] : nnVec[2]->back(),
+                                    nnVec[3]->size() > iZ-1 ? (*nnVec[3])[iZ-1] : nnVec[3]->back(),
+                                    nnVec[0]->size() > iZ   ? (*nnVec[0])[iZ]   : nnVec[0]->back(),
+                                    nnVec[1]->size() > iZ   ? (*nnVec[1])[iZ]   : nnVec[1]->back(),
+                                    nnVec[2]->size() > iZ   ? (*nnVec[2])[iZ]   : nnVec[2]->back(),
+                                    nnVec[3]->size() > iZ   ? (*nnVec[3])[iZ]   : nnVec[3]->back());
+            vols.push_back( vol );
             degenVols.push_back( vol );
           }
           }
@@ -10349,6 +10448,11 @@ bool _ViscousBuilder::refine(_SolidData& data)
         return error("Not supported type of element", data._index);
 
       } // switch ( nbNodes )
+
+      if ( group )
+        for ( size_t i = 0; i < vols.size(); ++i )
+          group->Add( vols[ i ]);
+
     } // while ( fIt->more() )
   } // loop on FACEs
 
@@ -10386,6 +10490,8 @@ namespace VISCOUS_3D
     PeriodicFaces( ShrinkFace* sf1, ShrinkFace* sf2 ): _shriFace{ sf1, sf2 } {}
     bool IncludeShrunk( const TopoDS_Face& face, const TopTools_MapOfShape& shrunkFaces ) const;
     bool MoveNodes( const TopoDS_Face& tgtFace );
+    void Clear() { _nnMap.clear(); }
+    bool IsEmpty() const { return _nnMap.empty(); }
   };
 
   //--------------------------------------------------------------------------------
@@ -10680,6 +10786,13 @@ namespace VISCOUS_3D
           return & _periodicFaces[ i ];
       return 0;
     }
+    void ClearPeriodic( const TopoDS_Face& face )
+    {
+      for ( size_t i = 0; i < _periodicFaces.size(); ++i )
+        if ( _periodicFaces[ i ]._shriFace[0]->IsSame( face ) ||
+             _periodicFaces[ i ]._shriFace[1]->IsSame( face ))
+          _periodicFaces[ i ].Clear();
+    }
   };
 
   //================================================================================
@@ -10689,6 +10802,7 @@ namespace VISCOUS_3D
   bool PeriodicFaces::IncludeShrunk( const TopoDS_Face&         face,
                                      const TopTools_MapOfShape& shrunkFaces ) const
   {
+    if ( IsEmpty() ) return false;
     return (( _shriFace[0]->IsSame( face ) && _shriFace[1]->IsShrunk( shrunkFaces )) ||
             ( _shriFace[1]->IsSame( face ) && _shriFace[0]->IsShrunk( shrunkFaces )));
   }
@@ -10709,7 +10823,8 @@ namespace VISCOUS_3D
     if ( iSrc != 0 )
     {
       trsfInverse = _trsf;
-      trsfInverse.Invert();
+      if ( !trsfInverse.Invert())
+        return false;
       trsf = &trsfInverse;
     }
     SMESHDS_Mesh* meshDS = dataSrc->GetHelper().GetMeshDS();
@@ -10747,10 +10862,10 @@ namespace VISCOUS_3D
       }
     }
     bool done = ( n2n == _nnMap.end() );
-    // cout << "MMMMMMMOOOOOOOOOOVVVVVVVVVVVEEEEEEEE "
-    //      << _shriFace[iSrc]->_subMesh->GetId() << " -> "
-    //      << _shriFace[iTgt]->_subMesh->GetId() << " -- "
-    //      << ( done ? "DONE" : "FAIL") << endl;
+    debugMsg( "PeriodicFaces::MoveNodes "
+              << _shriFace[iSrc]->_subMesh->GetId() << " -> "
+              << _shriFace[iTgt]->_subMesh->GetId() << " -- "
+              << ( done ? "DONE" : "FAIL"));
 
     return done;
   }
@@ -11210,6 +11325,8 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
             getMeshDS()->RemoveFreeNode( n, smDS, /*fromGroups=*/false );
         }
       }
+      _periodicity->ClearPeriodic( F );
+
       // restore position and UV of target nodes
       gp_Pnt p;
       for ( size_t iS = 0; iS < subEOS.size(); ++iS )
@@ -11398,7 +11515,7 @@ bool _ViscousBuilder::shrink(_SolidData& theData)
 bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
                                            _EdgesOnShape&         eos,
                                            SMESH_MesherHelper&    helper,
-                                           const SMESHDS_SubMesh* faceSubMesh)
+                                           const SMESHDS_SubMesh* /*faceSubMesh*/)
 {
   const SMDS_MeshNode* srcNode = edge._nodes[0];
   const SMDS_MeshNode* tgtNode = edge._nodes.back();
@@ -11452,6 +11569,13 @@ bool _ViscousBuilder::prepareEdgeToShrink( _LayerEdge&            edge,
     if ( !n2 )
       return error(SMESH_Comment("Wrongly meshed EDGE ") << getMeshDS()->ShapeToIndex( E ));
 
+    if ( n2 == tgtNode ) // for 3D_mesh_GHS3D_01/B1
+    {
+      // shrunk by other SOLID
+      edge.Set( _LayerEdge::SHRUNK ); // ???
+      return true;
+    }
+
     double uSrc = helper.GetNodeU( E, srcNode, n2 );
     double uTgt = helper.GetNodeU( E, tgtNode, srcNode );
     double u2   = helper.GetNodeU( E, n2,      srcNode );
@@ -11680,7 +11804,7 @@ void _ViscousBuilder::fixBadFaces(const TopoDS_Face&          F,
  */
 //================================================================================
 
-bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& surface,
+bool _LayerEdge::SetNewLength2d( Handle(Geom_Surface)& /*surface*/,
                                  const TopoDS_Face&    F,
                                  _EdgesOnShape&        eos,
                                  SMESH_MesherHelper&   helper )