Salome HOME
Add layers imprinting on faces.
authorChristophe Bourcier <christophe.bourcier@cea.fr>
Thu, 16 Mar 2017 08:49:57 +0000 (09:49 +0100)
committerChristophe Bourcier <christophe.bourcier@cea.fr>
Thu, 16 Mar 2017 08:49:57 +0000 (09:49 +0100)
Only works with tetra-dominant core in MeshGems 2.4-5. It will be fixed in next version of MeshGems.

15 files changed:
idl/HYBRIDPlugin_Algorithm.idl
src/GUI/HYBRIDPluginGUI_Enums.h
src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx
src/GUI/HYBRIDPluginGUI_HypothesisCreator.h
src/GUI/HYBRIDPlugin_msg_en.ts
src/GUI/HYBRIDPlugin_msg_fr.ts
src/GUI/HYBRIDPlugin_msg_ja.ts
src/HYBRIDPlugin/HYBRIDPluginBuilder.py
src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx
src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.hxx
src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx
src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx
src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx
src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx
tests/test_layers_imprinting.py [new file with mode: 0644]

index 29893d2e3f6dd0511fbd3143820ca7dd214891e6..a226d813d464ecd51decf335d44d2c4dd590f285 100644 (file)
@@ -83,6 +83,11 @@ module HYBRIDPlugin
      */
     void SetFacesWithLayers(in SMESH::long_array faceIDs);
     SMESH::long_array GetFacesWithLayers();
+    /*!
+     * To imprint layers on given faces.
+     */
+    void SetFacesWithImprinting(in SMESH::long_array faceIDs);
+    SMESH::long_array GetFacesWithImprinting();
     /*!
      * To make groups of volumes of different domains when mesh is generated from skin.
      * Default is to make groups.
index c351ed34ea4c900e0d55dfa01639b6fdb3f1ea44..c834884567b00f44b4e1a96d23c468402e58218e 100644 (file)
@@ -30,7 +30,8 @@ enum {
   STD_TAB = 0,
   ADV_TAB,
   ENF_MESH_TAB,
-  FACE_SEL_TAB
+  FACE_SEL_LAYERS_TAB,
+  FACE_SEL_IMPRINTING_TAB
 };
 
 // Enforced vertices array columns
index 6ffdef7819d867f06c71aac9e98566474bbcf153..9165bb15d2970951438a09f7ad297c21be3ac97e 100644 (file)
@@ -689,30 +689,44 @@ QFrame* HYBRIDPluginGUI_HypothesisCreator::buildFrame()
   anEnfMeshLayout->setRowStretch(ENF_MESH_MESH, 10);
 
 
-  // selection of faces
+  // selection of faces for layers
 
-  QWidget* faceSelGroup = new QWidget( dlg() );
-  QGridLayout* faceSelLayout = new QGridLayout( faceSelGroup );
+  QWidget* faceSelLayersGroup = new QWidget( dlg() );
+  QGridLayout* faceSelLayersLayout = new QGridLayout( faceSelLayersGroup );
 
-  QLabel* facesLbl = new QLabel( tr("HYBRID_FACE_IDS"), faceSelGroup );
-  faceSelLayout->addWidget( facesLbl, 0, 0 );
+  QLabel* facesLbl = new QLabel( tr("HYBRID_FACE_IDS"), faceSelLayersGroup );
+  faceSelLayersLayout->addWidget( facesLbl, 0, 0 );
 
-  myFaceSelector = new StdMeshersGUI_SubShapeSelectorWdg( faceSelGroup, TopAbs_FACE, true, true );
+  myFaceSelectorLayers = new StdMeshersGUI_SubShapeSelectorWdg( faceSelLayersGroup, TopAbs_FACE, true, true );
   QString aMainEntry = SMESHGUI_GenericHypothesisCreator::getMainShapeEntry();
   QString aSubEntry  = SMESHGUI_GenericHypothesisCreator::getShapeEntry();
-  myFaceSelector->SetGeomShapeEntry( aSubEntry, aMainEntry );
-  faceSelLayout->addWidget( myFaceSelector, 1, 0, 2, 2 );
-  faceSelLayout->setRowStretch( 1, 10);
+  myFaceSelectorLayers->SetGeomShapeEntry( aSubEntry, aMainEntry );
+  faceSelLayersLayout->addWidget( myFaceSelectorLayers, 1, 0, 2, 2 );
+  faceSelLayersLayout->setRowStretch( 1, 10);
 
+  // selection of faces for imprinting
+
+  QWidget* faceSelImprintingGroup = new QWidget( dlg() );
+  QGridLayout* faceSelImprintingLayout = new QGridLayout( faceSelImprintingGroup );
+
+  QLabel* facesLblImprinting = new QLabel( tr("HYBRID_FACE_IDS"), faceSelImprintingGroup );
+  faceSelImprintingLayout->addWidget( facesLblImprinting, 0, 0 );
+
+  myFaceSelectorImprinting = new StdMeshersGUI_SubShapeSelectorWdg( faceSelImprintingGroup, TopAbs_FACE, true, true );
+  myFaceSelectorImprinting->SetGeomShapeEntry( aSubEntry, aMainEntry );
+  faceSelImprintingLayout->addWidget( myFaceSelectorImprinting, 1, 0, 2, 2 );
+  faceSelImprintingLayout->setRowStretch( 1, 10);
 
   // add tabs
   tab->insertTab( STD_TAB, myStdGroup, tr( "SMESH_ARGUMENTS" ) );
   tab->insertTab( ADV_TAB, myAdvGroup, tr( "HYBRID_ADV_ARGS" ) );
   tab->insertTab( ENF_MESH_TAB, myEnfMeshGroup, tr( "HYBRID_ENFORCED_MESHES" ) );
   if ( aMainEntry.isEmpty() && aSubEntry.isEmpty() ) // mesh not based of geometry
-    faceSelGroup->hide();
-  else
-    tab->insertTab( FACE_SEL_TAB, faceSelGroup, tr( "HYBRID_FACES_TAB" ));
+    faceSelLayersGroup->hide();
+  else {
+    tab->insertTab( FACE_SEL_LAYERS_TAB, faceSelLayersGroup, tr( "HYBRID_FACES_LAYERS_TAB" ));
+    tab->insertTab( FACE_SEL_IMPRINTING_TAB, faceSelImprintingGroup, tr( "HYBRID_FACES_IMPRINTING_TAB" ));
+  }
   tab->setCurrentIndex( STD_TAB );
 
   // connections
@@ -1455,8 +1469,10 @@ void HYBRIDPluginGUI_HypothesisCreator::onTabChanged( int )
 {
   myEnfVertexWdg->deactivateSelection();
   myEnfMeshWdg->deactivateSelection();
-  myFaceSelector->ActivateSelection( false );
-  myFaceSelector->ShowPreview( false );
+  myFaceSelectorLayers->ActivateSelection( false );
+  myFaceSelectorLayers->ShowPreview( false );
+  myFaceSelectorImprinting->ActivateSelection( false );
+  myFaceSelectorImprinting->ShowPreview( false );
 }
 
 void HYBRIDPluginGUI_HypothesisCreator::updateWidgets()
@@ -1481,8 +1497,10 @@ void HYBRIDPluginGUI_HypothesisCreator::updateWidgets()
   addEnfMeshButton->setEnabled(enabled);
   removeEnfMeshButton->setEnabled(enabled);
   myEnfMeshWdg->setEnabled(enabled);
-  if ( QTabWidget* tab = qobject_cast<QTabWidget*>( myStdGroup->parentWidget()->parentWidget() ))
-    tab->setTabEnabled( FACE_SEL_TAB, enabled );
+  if ( QTabWidget* tab = qobject_cast<QTabWidget*>( myStdGroup->parentWidget()->parentWidget() )) {
+    tab->setTabEnabled( FACE_SEL_LAYERS_TAB, enabled );
+    tab->setTabEnabled( FACE_SEL_IMPRINTING_TAB, enabled );
+  }
 }
 
 bool HYBRIDPluginGUI_HypothesisCreator::checkParams(QString& msg) const
@@ -1530,7 +1548,8 @@ void HYBRIDPluginGUI_HypothesisCreator::retrieveParams() const
   else
     myCoreSizeSpin                -> setValue( data.myCoreSize );
   myMultinormalsAngleSpin         -> setValue( data.myMultinormalsAngle );
-  myFaceSelector                  ->SetListOfIDs( data.myFaceWLIds );
+  myFaceSelectorLayers            ->SetListOfIDs( data.myFaceWLIds );
+  myFaceSelectorImprinting        ->SetListOfIDs( data.myFaceWIIds );
 
   myAdvWidget->workingDirectoryLineEdit       ->setText   ( data.myWorkingDir );
   myAdvWidget->keepWorkingFilesCheck          ->setChecked( data.myKeepFiles );
@@ -1761,6 +1780,7 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromHypo( HYBRIDHypothesisData
   h_data.myMultinormalsAngle          = h->GetMultinormalsAngle();
   h_data.myNbOfBoundaryLayers         = h->GetNbOfBoundaryLayers();
   h_data.myFaceWLIds                  = h->GetFacesWithLayers();
+  h_data.myFaceWIIds                  = h->GetFacesWithImprinting();
 
   h_data.myLayersOnAllWrap            = h->GetLayersOnAllWrap();
   h_data.myToMeshHoles                = h->GetToMeshHoles();
@@ -1872,6 +1892,7 @@ bool HYBRIDPluginGUI_HypothesisCreator::storeParamsToHypo( const HYBRIDHypothesi
     if ( h->GetNbOfBoundaryLayers() != h_data.myNbOfBoundaryLayers )
       h->SetNbOfBoundaryLayers       ( h_data.myNbOfBoundaryLayers );
     h->SetFacesWithLayers( h_data.myFaceWLIds );
+    h->SetFacesWithImprinting( h_data.myFaceWIIds );
 
     if ( h->GetKeepFiles() != h_data.myKeepFiles)
       h->SetKeepFiles       ( h_data.myKeepFiles);
@@ -1993,7 +2014,8 @@ bool HYBRIDPluginGUI_HypothesisCreator::readParamsFromWidgets( HYBRIDHypothesisD
   h_data.myBoundaryLayersProgression  = myBoundaryLayersProgressionSpin -> value();
   h_data.myCoreSize                   = myCoreSizeSpin->text().isEmpty() ? 0.0 : myCoreSizeSpin -> value();
   h_data.myMultinormalsAngle          = myMultinormalsAngleSpin -> value();
-  h_data.myFaceWLIds                  = myFaceSelector->GetListOfIDs();
+  h_data.myFaceWLIds                  = myFaceSelectorLayers->GetListOfIDs();
+  h_data.myFaceWIIds                  = myFaceSelectorImprinting->GetListOfIDs();
 
   h_data.myKeepFiles                  = myAdvWidget->keepWorkingFilesCheck->isChecked();
   h_data.myWorkingDir                 = myAdvWidget->workingDirectoryLineEdit->text().trimmed();
index 19ae823371225b9140cff5cd84fb36e22ca7125f..e74d8c376354acfb055369a1f2cc5fdb9fe4bdc4 100644 (file)
@@ -164,7 +164,10 @@ typedef struct
           myCoreSize,
           myMultinormalsAngle;
   short   myNbOfBoundaryLayers;
+  // IDs of faces with layers
   SMESH::long_array_var myFaceWLIds;
+  // IDs of faces with imprinting
+  SMESH::long_array_var myFaceWIIds;
 
 } HYBRIDHypothesisData;
 
@@ -277,7 +280,8 @@ private:
   SMESHGUI_SpinBox*   myMultinormalsAngleSpin;
   QCheckBox*          mySmoothNormalsCheck;
 
-  StdMeshersGUI_SubShapeSelectorWdg* myFaceSelector;
+  StdMeshersGUI_SubShapeSelectorWdg* myFaceSelectorLayers;
+  StdMeshersGUI_SubShapeSelectorWdg* myFaceSelectorImprinting;
 };
 
 class EnforcedVertexTableWidgetDelegate : public QItemDelegate
index 77a630acf89cb00aa3eba2c86c80b5c3297eaab5..a61d576084e8d0aaee93dba589d0f43bd1c76d0c 100644 (file)
@@ -319,9 +319,13 @@ downward means inward and upward means outward ...
         <translation>&lt;b&gt;Warning&lt;/b&gt;: Enforced meshes are currently only taken into account for meshes w/o associated geometry.</translation>
     </message>
     <message>
-        <source>HYBRID_FACES_TAB</source>
+        <source>HYBRID_FACES_LAYERS_TAB</source>
         <translation>Faces with layers</translation>
     </message>
+    <message>
+        <source>HYBRID_FACES_IMPRINTING_TAB</source>
+        <translation>Faces with imprinting</translation>
+    </message>
     <message>
         <source>HYBRID_FACE_IDS</source>
         <translation>Face IDs</translation>
index 2fa24d463726e59e08014f7ee705472c1bc86205..a189df015f06d79b9b075b6a47ddb0b26eb7dd81 100755 (executable)
@@ -319,5 +319,17 @@ en conséquence au dessous signifie à l&apos;intérieur et au dessus signifie 
         <source>HYBRID_ENF_MESH_INFO</source>
         <translation>&lt;b&gt;Attention&lt;/b&gt;: Les éléments de contraintes ne sont pris en compte que pour des maillage sans géométrie associée.</translation>
     </message>
+    <message>
+        <source>HYBRID_FACES_LAYERS_TAB</source>
+        <translation>Faces avec couche prismatique</translation>
+    </message>
+    <message>
+        <source>HYBRID_FACES_IMPRINTING_TAB</source>
+        <translation>Faces avec empreinte</translation>
+    </message>
+    <message>
+        <source>HYBRID_FACE_IDS</source>
+        <translation>Numéros des faces</translation>
+    </message>
 </context>
 </TS>
index ccc5cdcd27abfacade733348f4238c6289035723..2e7a329a1e98c9db4571dde061bf6a663a805e00 100644 (file)
@@ -319,5 +319,17 @@ downward means inward and upward means outward ...
       <source>HYBRID_ENF_MESH_INFO</source>
       <translation>&lt;b&gt;警告&lt;/b&gt;: 強制メッシュは現在 w/o がジオメトリに関連付けたメッシュの説明を考慮のみしています。</translation>
     </message>
+    <message>
+        <source>HYBRID_FACES_LAYERS_TAB</source>
+        <translation type="unfinished">Faces with layers</translation>
+    </message>
+    <message>
+        <source>HYBRID_FACES_IMPRINTING_TAB</source>
+        <translation type="unfinished">Faces with imprinting</translation>
+    </message>
+    <message>
+        <source>HYBRID_FACE_IDS</source>
+        <translation type="unfinished">Face IDs</translation>
+    </message>
   </context>
 </TS>
index 574f151b9ce9bad5b7b6f78273e3a0b18b459a5c..c2ea69c23054b8428a194ef37444b6cb833449d0 100644 (file)
@@ -97,7 +97,7 @@ class HYBRID_Algorithm(Mesh_Algorithm):
         self.Parameters().SetLayersOnAllWrap(toMesh)
         pass
 
-    ## To mesh "holes" in a solid or not. Default is to mesh.
+    ## To mesh layers on given faces.
     #  @param faceIDs faces or face IDs to construct boundary layers on
     def SetFacesWithLayers(self, faceIDs):
         import GEOM
@@ -120,6 +120,29 @@ class HYBRID_Algorithm(Mesh_Algorithm):
             self.SetLayersOnAllWrap( False )
         pass
 
+    ## To imprint the layers on given faces.
+    #  @param faceIDs faces or face IDs to imprint the boundary layers on
+    def SetFacesWithImprinting(self, faceIDs):
+        import GEOM
+        ids = []
+        if not isinstance( faceIDs, list ) and not isinstance( faceIDs, tuple ):
+            faceIDs = [ faceIDs ]
+        for fid in faceIDs:
+            if isinstance( fid, int ):
+                ids.append( fid )
+            elif isinstance( fid, GEOM._objref_GEOM_Object):
+                faces = self.mesh.geompyD.SubShapeAll( fid, self.mesh.geompyD.ShapeType["FACE"])
+                for f in faces:
+                    ids.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, f ))
+            else:
+                raise TypeError, \
+                    "Face should be either ID or GEOM_Object, not %s" % type(fid)
+            pass
+        self.Parameters().SetFacesWithImprinting(ids)
+        if ids:
+            self.SetLayersOnAllWrap( False )
+        pass
+
     """
     obsolete
     ## To mesh "holes" in a solid or not. Default is to mesh.
index 312efe3bc71a47915492209e1a62fe6b26b57b9f..e6891c34b6cda9fb9c2aaa80a6f632dd5e127c64 100644 (file)
@@ -351,9 +351,28 @@ static bool readGMFFile(MG_HYBRID_API*                          MGOutput,
   SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS();
   const bool hasGeom = ( theHelper->GetMesh()->HasShapeToMesh() );
 
-  int nbInitialNodes = theNodeByHybridId.size();
+  // if imprinting, the original mesh faces are modified
+  // => we clear all the faces to retrieve them from Hybrid output mesh.
+  std::vector<int> facesWithImprinting = theAlgo->getHyp()->GetFacesWithImprinting();
+
+  if ( ! facesWithImprinting.empty() ) {
+#ifdef _DEBUG_
+      std::cout << "Imprinting => Clear original mesh" << std::endl;
+#endif
+      SMDS_ElemIteratorPtr eIt = theMeshDS->elementsIterator();
+      while( eIt->more() )
+        theMeshDS->RemoveFreeElement( eIt->next(), /*sm=*/0 );
+      SMDS_NodeIteratorPtr nIt = theMeshDS->nodesIterator();
+      while ( nIt->more() )
+        theMeshDS->RemoveFreeNode( nIt->next(), /*sm=*/0 );
+
+      theNodeByHybridId.clear();
+      theFaceByHybridId.clear();
+  }
+
   int nbMeshNodes = theMeshDS->NbNodes();
-  
+  int nbInitialNodes = theNodeByHybridId.size();
+
   const bool isQuadMesh = 
     theHelper->GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
     theHelper->GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
@@ -591,11 +610,21 @@ static bool readGMFFile(MG_HYBRID_API*                          MGOutput,
             aCreatedElem = theHelper->AddFace( node[0], node[1], node[2], noID, force3d );
             if (aFaceGroupByHybridId.size() && !aFaceGroupByHybridId[iElem].empty())
               addElemInMeshGroup(theHelper->GetMesh(), aCreatedElem, aFaceGroupByHybridId[iElem], groupsToRemove);
+            // add element in shape for groups on geom to work
+            theMeshDS->SetMeshElementOnShape( aCreatedElem, domainID[iElem] );
+            for ( int iN = 0; iN < 3; ++iN )
+              if ( node[iN]->getshapeId() < 1 )
+                theMeshDS->SetNodeOnFace( node[iN], domainID[iElem] );
           }
           break;
         case GmfQuadrilaterals:
           if (fullyCreatedElement) {
             aCreatedElem = theHelper->AddFace( node[0], node[1], node[2], node[3], noID, force3d );
+            // add element in shape for groups on geom to work
+            theMeshDS->SetMeshElementOnShape( aCreatedElem, domainID[iElem] );
+            for ( int iN = 0; iN < 3; ++iN )
+              if ( node[iN]->getshapeId() < 1 )
+                theMeshDS->SetNodeOnFace( node[iN], domainID[iElem] );
           }
           break;
         case GmfTetrahedra:
index face76b2f6d3662aaa533d586b9cda8083be9046..16f51958e4e665368bb3e84176615efe7a1e198d 100644 (file)
@@ -70,6 +70,8 @@ public:
 
   static const char* Name() { return "HYBRID_3D"; }
 
+  const HYBRIDPlugin_Hypothesis* getHyp() {return _hyp ;}
+
 protected:
   const HYBRIDPlugin_Hypothesis*   _hyp;
   //const StdMeshers_ViscousLayers* _viscousLayersHyp;
index de92a756b2e2f23eb4de5a81c7eb5d1db8783c7d..3d99a624f9e033e64529c26747bc27db1ff85b01 100644 (file)
@@ -129,6 +129,32 @@ const std::vector<int>& HYBRIDPlugin_Hypothesis::GetFacesWithLayers() const
   return myFacesWithLayers;
 }
 
+//=======================================================================
+//function : SetFacesWithImprinting
+//purpose  : Set IDs of faces to grow the layers on
+//=======================================================================
+
+bool HYBRIDPlugin_Hypothesis::SetFacesWithImprinting(const std::vector<int>& theVal)
+{
+  if ( myFacesWithImprinting != theVal )
+  {
+    myFacesWithImprinting = theVal;
+    NotifySubMeshesHypothesisModification();
+    return true;
+  }
+  return false;
+}
+
+//=======================================================================
+//function : GetFacesWithImprinting
+//purpose  : Return IDs of faces to grow the layers on
+//=======================================================================
+
+const std::vector<int>& HYBRIDPlugin_Hypothesis::GetFacesWithImprinting() const
+{
+  return myFacesWithImprinting;
+}
+
 //=======================================================================
 //function : SetToMeshHoles
 //=======================================================================
@@ -1440,6 +1466,10 @@ std::ostream & HYBRIDPlugin_Hypothesis::SaveTo(std::ostream & save)
   for ( size_t i = 0; i < myFacesWithLayers.size(); ++i )
     save << " " << myFacesWithLayers[i];
 
+  save << " " << myFacesWithImprinting.size();
+  for ( size_t i = 0; i < myFacesWithImprinting.size(); ++i )
+    save << " " << myFacesWithImprinting[i];
+
   return save;
 }
 
@@ -1770,6 +1800,20 @@ std::istream & HYBRIDPlugin_Hypothesis::LoadFrom(std::istream & load)
         myFacesWithLayers.push_back( i );
     }
   }
+
+  if ( isOK )
+  {
+    i = atoi( separator.c_str() );
+    isOK = ( i >= 0 );
+    if ( isOK )
+    {
+      myFacesWithImprinting.reserve( i );
+      while (( myFacesWithImprinting.size() < myFacesWithImprinting.capacity() ) &&
+             ( isOK = static_cast<bool>(load >> i)) )
+        myFacesWithImprinting.push_back( i );
+    }
+  }
+
   return load;
 }
 
@@ -1877,22 +1921,26 @@ std::string HYBRIDPlugin_Hypothesis::CommandToRun(const HYBRIDPlugin_Hypothesis*
   if ( !nolayers && hyp )
   {
     cmd << " --boundary_layer_size_mode " << ( layersOnAllWrap ? "global" : "local" );
-    cmd << " --boundary_layer_surface_tags ";
-    if ( layersOnAllWrap )
-    {
-      cmd << " 3 ";
-    }
-    else
+    
+    if ( !layersOnAllWrap )
     {
-      const std::vector<int>& faceIDs = hyp->GetFacesWithLayers();
-      const bool      hasEnforcedTria = !HYBRIDPlugin_Hypothesis::GetEnforcedTriangles(hyp).empty();
-      for ( size_t i = 0; i < faceIDs.size(); ++i )
-        cmd << faceIDs[i] << ",";
-      if ( hasEnforcedTria )
-        cmd << EnforcedTag();
-      cmd << " --boundary_layer_initial_height_on_surface_tags ";
-      for ( size_t i = 0; i < faceIDs.size() + hasEnforcedTria; ++i )
+      // faces with layers
+      const std::vector<int>& faceLayersIDs = hyp->GetFacesWithLayers();
+      if ( !faceLayersIDs.empty() )
+        cmd << " --boundary_layer_surface_tags ";
+      for ( size_t i = 0; i < faceLayersIDs.size(); ++i )
+        cmd << faceLayersIDs[i] << ",";
+      if ( !faceLayersIDs.empty() )
+        cmd << " --boundary_layer_initial_height_on_surface_tags ";
+      for ( size_t i = 0; i < faceLayersIDs.size(); ++i )
         cmd << hyp->myHeightFirstLayer << ",";
+
+      // faces with imprinting
+      const std::vector<int>& faceImprintingIDs = hyp->GetFacesWithImprinting();
+      if ( !faceImprintingIDs.empty() )
+        cmd << " --boundary_layer_imprinting yes --boundary_layer_imprinting_tags ";
+      for ( size_t i = 0; i < faceImprintingIDs.size(); ++i )
+        cmd << faceImprintingIDs[i] << ",";
     }
   }
 
index f4953fa019af14b126c3425792c90a0e0b9eef7f..f732da82eb0e173b8499dd52ec42f8d8690161b8 100644 (file)
@@ -134,6 +134,11 @@ public:
    */
   bool SetFacesWithLayers(const std::vector<int>& theVal);
   const std::vector<int>& GetFacesWithLayers() const;
+  /*!
+   * IDs of faces to imprint the layers on
+   */
+  bool SetFacesWithImprinting(const std::vector<int>& theVal);
+  const std::vector<int>& GetFacesWithImprinting() const;
   /*!
    * To make groups of volumes of different domains when mesh is generated from skin.
    * Default is to make groups.
@@ -426,6 +431,7 @@ private:
   bool             myToMeshHoles;
   bool             myLayersOnAllWrap;
   std::vector<int> myFacesWithLayers;
+  std::vector<int> myFacesWithImprinting;
   bool             myToMakeGroupsOfDomains;
   double           myMaximumMemory;
   double           myInitialMemory;
index 3aa6efa4d39a181a4e4c8f224c7b43c700873cdb..d5422004e26950414c8037386a986664f7a7a13b 100644 (file)
@@ -116,6 +116,35 @@ SMESH::long_array* HYBRIDPlugin_Hypothesis_i::GetFacesWithLayers()
   return ids._retn();
 }
 
+//=======================================================================
+//function : SetFacesWithImprinting
+//=======================================================================
+
+void HYBRIDPlugin_Hypothesis_i::SetFacesWithImprinting(const ::SMESH::long_array& theVal)
+{
+  std::vector<int> ids( theVal.length() );
+  for ( size_t i = 0; i < ids.size(); ++i )
+   ids[i] = theVal[i];
+
+  bool valueChanged = this->GetImpl()->SetFacesWithImprinting(ids);
+  if (valueChanged)
+    SMESH::TPythonDump() << _this() << ".SetFacesWithImprinting( "<< theVal << " )";
+}
+
+//=======================================================================
+//function : GetFacesWithImprinting
+//=======================================================================
+
+SMESH::long_array* HYBRIDPlugin_Hypothesis_i::GetFacesWithImprinting()
+{
+  const std::vector<int>& idsVec = this->GetImpl()->GetFacesWithImprinting();
+  SMESH::long_array_var ids = new SMESH::long_array;
+  ids->length( idsVec.size() );
+  for ( size_t i = 0; i < idsVec.size(); ++i )
+    ids[i] = idsVec[i];
+  return ids._retn();
+}
+
 //=======================================================================
 //function : SetToMeshHoles
 //=======================================================================
index 858436ac9711865659a8683a90b86cbae06e70fb..609888385477ed0c4b88ce8969f7611440814b05 100644 (file)
@@ -60,6 +60,11 @@ class HYBRIDPLUGIN_EXPORT HYBRIDPlugin_Hypothesis_i:
    */
   void SetFacesWithLayers(const SMESH::long_array& faceIDs);
   SMESH::long_array* GetFacesWithLayers();
+  /*!
+   * IDs of faces to imprint the layers on
+   */
+  void SetFacesWithImprinting(const SMESH::long_array& faceIDs);
+  SMESH::long_array* GetFacesWithImprinting();
   /*!
    * To mesh "layers on all wrap". Default is to mesh.
    */
diff --git a/tests/test_layers_imprinting.py b/tests/test_layers_imprinting.py
new file mode 100644 (file)
index 0000000..8f04116
--- /dev/null
@@ -0,0 +1,225 @@
+# -*- coding: utf-8 -*-
+
+###
+### This file is generated automatically by SALOME v7.6.0 with dump python functionality
+###
+
+import sys
+import salome
+
+salome.salome_init()
+theStudy = salome.myStudy
+
+###
+### GEOM component
+###
+
+import GEOM
+from salome.geom import geomBuilder
+import math
+import SALOMEDS
+
+
+geompy = geomBuilder.New(theStudy)
+
+O = geompy.MakeVertex(0, 0, 0)
+OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
+OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+Cylinder_1 = geompy.MakeCylinderRH(0.5, 5)
+Cylinder_2 = geompy.MakeCylinderRH(0.3, 3)
+Rotation_1 = geompy.MakeRotation(Cylinder_2, OY, -90*math.pi/180.0)
+Translation_1 = geompy.MakeTranslation(Rotation_1, 0, 0, 1.5)
+piquage = geompy.MakeFuseList([Cylinder_1, Translation_1], True, True)
+[Outlet] = geompy.SubShapes(piquage, [15])
+[Inlet_z,Inlet_x] = geompy.SubShapes(piquage, [3, 22])
+[corner] = geompy.SubShapes(piquage, [14])
+geomObj_1 = geompy.MakeVertex(0, 0, 0)
+geomObj_2 = geompy.MakeVectorDXDYDZ(1, 0, 0)
+geomObj_3 = geompy.MakeVectorDXDYDZ(0, 1, 0)
+geomObj_4 = geompy.MakeVectorDXDYDZ(0, 0, 1)
+Wall = geompy.CreateGroup(piquage, geompy.ShapeType["FACE"])
+geompy.UnionIDs(Wall, [7, 17])
+geompy.addToStudy( O, 'O' )
+geompy.addToStudy( OX, 'OX' )
+geompy.addToStudy( OY, 'OY' )
+geompy.addToStudy( OZ, 'OZ' )
+geompy.addToStudy( Cylinder_1, 'Cylinder_1' )
+geompy.addToStudy( Cylinder_2, 'Cylinder_2' )
+geompy.addToStudy( Rotation_1, 'Rotation_1' )
+geompy.addToStudy( Translation_1, 'Translation_1' )
+geompy.addToStudy( piquage, 'piquage' )
+geompy.addToStudyInFather( piquage, Inlet_x, 'Inlet_x' )
+geompy.addToStudyInFather( piquage, Outlet, 'Outlet' )
+geompy.addToStudyInFather( piquage, Wall, 'Wall' )
+geompy.addToStudyInFather( piquage, Inlet_z, 'Inlet_z' )
+geompy.addToStudyInFather( piquage, corner, 'corner' )
+
+geom_groups = [Inlet_x, Inlet_z, Outlet, Wall]
+d_geom_groups = {}
+
+###
+### SMESH component
+###
+
+import  SMESH, SALOMEDS
+from salome.smesh import smeshBuilder
+
+from salome.StdMeshers import StdMeshersBuilder
+
+smesh = smeshBuilder.New(theStudy)
+
+
+# Viscous layers without imprinting
+# =================================
+
+Mesh_1 = smesh.Mesh(piquage, "Mesh_without_imprinting")
+NETGEN_2D = Mesh_1.Triangle(algo=smeshBuilder.NETGEN_1D2D)
+NETGEN_2D_Parameters = NETGEN_2D.Parameters()
+
+NETGEN_2D_Parameters.SetMinSize( 0.01 )
+NETGEN_2D_Parameters.SetLocalSizeOnShape(corner, 0.01)
+NETGEN_2D_Parameters.SetFineness( 5 )
+NETGEN_2D_Parameters.SetGrowthRate( 0.1 )
+NETGEN_2D_Parameters.SetNbSegPerEdge( 2 )
+NETGEN_2D_Parameters.SetNbSegPerRadius( 3 )
+
+MG_Hybrid = Mesh_1.Tetrahedron(algo=smeshBuilder.HYBRID)
+MG_Hybrid_Parameters_1 = MG_Hybrid.Parameters()
+MG_Hybrid_Parameters_1.SetLayersOnAllWrap( 0 )
+MG_Hybrid_Parameters_1.SetElementGeneration( 0 )
+MG_Hybrid_Parameters_1.SetHeightFirstLayer( 0.01 )
+MG_Hybrid_Parameters_1.SetBoundaryLayersProgression( 1.1 )
+MG_Hybrid_Parameters_1.SetNbOfBoundaryLayers( 3 )
+MG_Hybrid_Parameters_1.SetFacesWithLayers( [ 7, 17 ] )
+
+
+isDone = Mesh_1.Compute()
+
+if not isDone:
+  raise Exception("Error when computing Mesh_without_imprinting")
+
+d_groups_1 = {}
+
+for geom_group in geom_groups:
+  name = geom_group.GetName()
+  gr = Mesh_1.Group(geom_group)
+  d_groups_1[name] = gr
+  d_geom_groups[name] = geom_group
+
+assert Mesh_1.NbQuadrangles() == 0
+
+shape_volume = geompy.BasicProperties(piquage)[2]
+
+# Compare whole mesh volume
+volume_error_1 = abs(shape_volume-Mesh_1.GetVolume())/shape_volume
+
+assert volume_error_1 < 0.015
+
+# Viscous layers with imprinting
+# ==============================
+
+Mesh_2 = smesh.Mesh(piquage, "Mesh_with_imprinting")
+
+NETGEN_2D_1_1 = Mesh_2.Triangle(algo=smeshBuilder.NETGEN_1D2D)
+status = Mesh_2.AddHypothesis(NETGEN_2D_Parameters)
+
+MG_Hybrid_2 = Mesh_2.Tetrahedron(algo=smeshBuilder.HYBRID)
+MG_Hybrid_Parameters_2 = MG_Hybrid_2.Parameters()
+MG_Hybrid_Parameters_2.SetLayersOnAllWrap( 0 )
+MG_Hybrid_Parameters_2.SetElementGeneration( 0 )
+MG_Hybrid_Parameters_2.SetHeightFirstLayer( 0.01 )
+MG_Hybrid_Parameters_2.SetBoundaryLayersProgression( 1.1 )
+MG_Hybrid_Parameters_2.SetNbOfBoundaryLayers( 3 )
+MG_Hybrid_Parameters_2.SetFacesWithLayers( [ 7, 17 ] )
+MG_Hybrid_Parameters_2.SetFacesWithImprinting( [ 22, 15, 3 ] )
+
+isDone = Mesh_2.Compute()
+
+if not isDone:
+  raise Exception("Error when computing Mesh_with_imprinting")
+
+#assert Mesh_2.NbQuadrangles() > 0
+
+d_groups_2 = {}
+
+for geom_group in geom_groups:
+  name = geom_group.GetName()
+  gr = Mesh_2.Group(geom_group)
+  d_groups_2[name] = gr
+
+faces_imprinted = ["Inlet_x", "Inlet_z", "Outlet"]
+
+# Check viscous layers with imprinting
+for name in faces_imprinted:
+  geom_area = geompy.BasicProperties(d_geom_groups[name])[1]
+  gr_1 = d_groups_1[name]
+  gr_2 = d_groups_2[name]
+  #assert gr_1.Size() > 0
+  assert gr_2.Size() > 0
+  # Nb of quadrangles is in 7th index of mesh info
+  assert gr_2.GetMeshInfo()[7] > 0
+
+  # Compare mesh group and geom group
+  area_error_1 = abs(geom_area-smesh.GetArea(gr_2))/geom_area
+  assert area_error_1 < 0.025
+  # Compare mesh group with imprinting and mesh group without imprinting
+  area_error_2 = abs(smesh.GetArea(gr_1)-smesh.GetArea(gr_2))/smesh.GetArea(gr_1)
+  assert area_error_2 < 1e-10
+
+# Compare whole mesh volume
+mesh_2_volume = Mesh_2.GetVolume()
+volume_error_2 = abs(shape_volume-mesh_2_volume)/shape_volume
+
+assert volume_error_2 < 0.015
+
+# Viscous layers with imprinting set by groups
+# ============================================
+
+Mesh_3 = smesh.Mesh(piquage, "Mesh_with_imprinting_set_by_groups")
+
+NETGEN_2D_1_1 = Mesh_3.Triangle(algo=smeshBuilder.NETGEN_1D2D)
+status = Mesh_3.AddHypothesis(NETGEN_2D_Parameters)
+
+MG_Hybrid_3 = Mesh_3.Tetrahedron(algo=smeshBuilder.HYBRID)
+MG_Hybrid_Parameters_3 = MG_Hybrid_3.Parameters()
+MG_Hybrid_Parameters_3.SetLayersOnAllWrap( 0 )
+MG_Hybrid_Parameters_3.SetElementGeneration( 0 )
+MG_Hybrid_Parameters_3.SetHeightFirstLayer( 0.01 )
+MG_Hybrid_Parameters_3.SetBoundaryLayersProgression( 1.1 )
+MG_Hybrid_Parameters_3.SetNbOfBoundaryLayers( 3 )
+MG_Hybrid_3.SetFacesWithLayers( Wall )
+MG_Hybrid_3.SetFacesWithImprinting( [ Inlet_x, Inlet_z, Outlet ] )
+
+isDone = Mesh_3.Compute()
+
+if not isDone:
+  raise Exception("Error when computing Mesh_with_imprinting_set_by_groups")
+
+d_groups_3 = {}
+
+for geom_group in geom_groups:
+  name = geom_group.GetName()
+  gr = Mesh_3.Group(geom_group)
+  d_groups_3[name] = gr
+
+# Compare whole mesh volume
+mesh_3_volume = Mesh_3.GetVolume()
+volume_error_3 = abs(mesh_2_volume-mesh_3_volume)/mesh_2_volume
+
+assert abs(mesh_3_volume-mesh_2_volume)/mesh_2_volume < 1e-10
+
+# Check viscous layers with imprinting
+for name in faces_imprinted:
+  gr_2 = d_groups_2[name]
+  gr_3 = d_groups_3[name]
+  assert gr_3.Size() > 0
+  # Nb of quadrangles is in 7th index of mesh info
+  assert gr_2.GetMeshInfo()[7] == gr_3.GetMeshInfo()[7]
+
+  # Compare mesh group with imprinting set by ids and mesh group with imprinting set by geom group
+  area_error_3 = abs(smesh.GetArea(gr_2)-smesh.GetArea(gr_3))/smesh.GetArea(gr_2)
+  assert area_error_3 < 1e-10
+
+if salome.sg.hasDesktop():
+  salome.sg.updateObjBrowser(1)