From 24d1db4b7fa90f4cb3fb0748f20f61e4240364d0 Mon Sep 17 00:00:00 2001 From: Christophe Bourcier Date: Thu, 16 Mar 2017 09:49:57 +0100 Subject: [PATCH] Add layers imprinting on faces. Only works with tetra-dominant core in MeshGems 2.4-5. It will be fixed in next version of MeshGems. --- idl/HYBRIDPlugin_Algorithm.idl | 5 + src/GUI/HYBRIDPluginGUI_Enums.h | 3 +- src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx | 58 +++-- src/GUI/HYBRIDPluginGUI_HypothesisCreator.h | 6 +- src/GUI/HYBRIDPlugin_msg_en.ts | 6 +- src/GUI/HYBRIDPlugin_msg_fr.ts | 12 + src/GUI/HYBRIDPlugin_msg_ja.ts | 12 + src/HYBRIDPlugin/HYBRIDPluginBuilder.py | 25 +- src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx | 33 ++- src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.hxx | 2 + src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx | 76 ++++-- src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx | 6 + .../HYBRIDPlugin_Hypothesis_i.cxx | 29 +++ .../HYBRIDPlugin_Hypothesis_i.hxx | 5 + tests/test_layers_imprinting.py | 225 ++++++++++++++++++ 15 files changed, 465 insertions(+), 38 deletions(-) create mode 100644 tests/test_layers_imprinting.py diff --git a/idl/HYBRIDPlugin_Algorithm.idl b/idl/HYBRIDPlugin_Algorithm.idl index 29893d2..a226d81 100644 --- a/idl/HYBRIDPlugin_Algorithm.idl +++ b/idl/HYBRIDPlugin_Algorithm.idl @@ -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. diff --git a/src/GUI/HYBRIDPluginGUI_Enums.h b/src/GUI/HYBRIDPluginGUI_Enums.h index c351ed3..c834884 100644 --- a/src/GUI/HYBRIDPluginGUI_Enums.h +++ b/src/GUI/HYBRIDPluginGUI_Enums.h @@ -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 diff --git a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx index 6ffdef7..9165bb1 100644 --- a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx +++ b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.cxx @@ -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( myStdGroup->parentWidget()->parentWidget() )) - tab->setTabEnabled( FACE_SEL_TAB, enabled ); + if ( QTabWidget* tab = qobject_cast( 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(); diff --git a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h index 19ae823..e74d8c3 100644 --- a/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h +++ b/src/GUI/HYBRIDPluginGUI_HypothesisCreator.h @@ -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 diff --git a/src/GUI/HYBRIDPlugin_msg_en.ts b/src/GUI/HYBRIDPlugin_msg_en.ts index 77a630a..a61d576 100644 --- a/src/GUI/HYBRIDPlugin_msg_en.ts +++ b/src/GUI/HYBRIDPlugin_msg_en.ts @@ -319,9 +319,13 @@ downward means inward and upward means outward ... <b>Warning</b>: Enforced meshes are currently only taken into account for meshes w/o associated geometry. - HYBRID_FACES_TAB + HYBRID_FACES_LAYERS_TAB Faces with layers + + HYBRID_FACES_IMPRINTING_TAB + Faces with imprinting + HYBRID_FACE_IDS Face IDs diff --git a/src/GUI/HYBRIDPlugin_msg_fr.ts b/src/GUI/HYBRIDPlugin_msg_fr.ts index 2fa24d4..a189df0 100755 --- a/src/GUI/HYBRIDPlugin_msg_fr.ts +++ b/src/GUI/HYBRIDPlugin_msg_fr.ts @@ -319,5 +319,17 @@ en conséquence au dessous signifie à l'intérieur et au dessus signifie HYBRID_ENF_MESH_INFO <b>Attention</b>: Les éléments de contraintes ne sont pris en compte que pour des maillage sans géométrie associée. + + HYBRID_FACES_LAYERS_TAB + Faces avec couche prismatique + + + HYBRID_FACES_IMPRINTING_TAB + Faces avec empreinte + + + HYBRID_FACE_IDS + Numéros des faces + diff --git a/src/GUI/HYBRIDPlugin_msg_ja.ts b/src/GUI/HYBRIDPlugin_msg_ja.ts index ccc5cdc..2e7a329 100644 --- a/src/GUI/HYBRIDPlugin_msg_ja.ts +++ b/src/GUI/HYBRIDPlugin_msg_ja.ts @@ -319,5 +319,17 @@ downward means inward and upward means outward ... HYBRID_ENF_MESH_INFO <b>警告</b>: 強制メッシュは現在 w/o がジオメトリに関連付けたメッシュの説明を考慮のみしています。 + + HYBRID_FACES_LAYERS_TAB + Faces with layers + + + HYBRID_FACES_IMPRINTING_TAB + Faces with imprinting + + + HYBRID_FACE_IDS + Face IDs + diff --git a/src/HYBRIDPlugin/HYBRIDPluginBuilder.py b/src/HYBRIDPlugin/HYBRIDPluginBuilder.py index 574f151..c2ea69c 100644 --- a/src/HYBRIDPlugin/HYBRIDPluginBuilder.py +++ b/src/HYBRIDPlugin/HYBRIDPluginBuilder.py @@ -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. diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx index 312efe3..e6891c3 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.cxx @@ -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 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: diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.hxx b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.hxx index face76b..16f5195 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.hxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_HYBRID.hxx @@ -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; diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx index de92a75..3d99a62 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.cxx @@ -129,6 +129,32 @@ const std::vector& 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& 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& 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(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& 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& 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& 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] << ","; } } diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx index f4953fa..f732da8 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis.hxx @@ -134,6 +134,11 @@ public: */ bool SetFacesWithLayers(const std::vector& theVal); const std::vector& GetFacesWithLayers() const; + /*! + * IDs of faces to imprint the layers on + */ + bool SetFacesWithImprinting(const std::vector& theVal); + const std::vector& 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 myFacesWithLayers; + std::vector myFacesWithImprinting; bool myToMakeGroupsOfDomains; double myMaximumMemory; double myInitialMemory; diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx index 3aa6efa..d542200 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.cxx @@ -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 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& 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 //======================================================================= diff --git a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx index 858436a..6098883 100644 --- a/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx +++ b/src/HYBRIDPlugin/HYBRIDPlugin_Hypothesis_i.hxx @@ -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 index 0000000..8f04116 --- /dev/null +++ b/tests/test_layers_imprinting.py @@ -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) -- 2.39.2