From 9ac965c0e3635a98daef92d9b8c9721e4795286f Mon Sep 17 00:00:00 2001 From: cconopoima Date: Tue, 23 May 2023 16:47:39 -0300 Subject: [PATCH] bos #32738 [CEA] Scaled Jacobian quality mesh measure for volumetric elements. Erase non tracke files Adding some comments on SMESH_Controls. Fixing compilation warning on SMDS_VolumeTool and add missing lines in interface files. Add implemented tests to tests.set Correction on SMESH_msg_fr and copyright msg of python test. --- doc/examples/filters_ex40.py | 9 + doc/examples/quality_controls_ex24.py | 24 ++ doc/examples/tests.set | 2 + doc/gui/images/scaled_jacobian.png | Bin 0 -> 2931 bytes doc/gui/images/scaled_jacobian_hexa.png | Bin 0 -> 34875 bytes doc/gui/images/scaled_jacobian_mesh_tetra.png | Bin 0 -> 35275 bytes doc/gui/images/scaled_jacobian_tetra.png | Bin 0 -> 34348 bytes doc/gui/input/about_quality_controls.rst | 4 +- doc/gui/input/scaled_jacobian.rst | 42 +++ doc/gui/input/tui_filters.rst | 18 + doc/gui/input/tui_quality_controls.rst | 10 + idl/SMESH_Filter.idl | 5 +- resources/mesh_scaled_jacobian.png | Bin 0 -> 7383 bytes src/Controls/SMESH_Controls.cxx | 64 ++++ src/Controls/SMESH_ControlsDef.hxx | 11 + src/OBJECT/SMESH_Actor.cxx | 9 +- src/OBJECT/SMESH_Actor.h | 2 +- src/SMDS/SMDS_VolumeTool.cxx | 355 +++++++++++++++++- src/SMDS/SMDS_VolumeTool.hxx | 3 + src/SMESHGUI/SMESHGUI.cxx | 13 +- src/SMESHGUI/SMESHGUI_FilterDlg.cxx | 3 + src/SMESHGUI/SMESHGUI_MeshInfo.cxx | 2 + src/SMESHGUI/SMESHGUI_Operations.h | 1 + src/SMESHGUI/SMESHGUI_Selection.cxx | 2 + src/SMESHGUI/SMESHGUI_SelectionProxy.cxx | 6 + src/SMESHGUI/SMESH_images.ts | 4 + src/SMESHGUI/SMESH_msg_en.ts | 20 + src/SMESHGUI/SMESH_msg_fr.ts | 16 + src/SMESHGUI/SMESH_msg_ja.ts | 18 +- src/SMESH_I/SMESH_2smeshpy.cxx | 3 + src/SMESH_I/SMESH_Filter_i.cxx | 28 ++ src/SMESH_I/SMESH_Filter_i.hxx | 13 + src/SMESH_I/SMESH_PythonDump.cxx | 1 + src/SMESH_SWIG/smeshBuilder.py | 15 + test/SMESH_controls_scaled_jacobian.py | 144 +++++++ test/tests.set | 1 + 36 files changed, 838 insertions(+), 10 deletions(-) create mode 100644 doc/examples/filters_ex40.py create mode 100644 doc/examples/quality_controls_ex24.py create mode 100644 doc/gui/images/scaled_jacobian.png create mode 100644 doc/gui/images/scaled_jacobian_hexa.png create mode 100644 doc/gui/images/scaled_jacobian_mesh_tetra.png create mode 100644 doc/gui/images/scaled_jacobian_tetra.png create mode 100644 doc/gui/input/scaled_jacobian.rst create mode 100644 resources/mesh_scaled_jacobian.png create mode 100644 test/SMESH_controls_scaled_jacobian.py diff --git a/doc/examples/filters_ex40.py b/doc/examples/filters_ex40.py new file mode 100644 index 000000000..8abb7e413 --- /dev/null +++ b/doc/examples/filters_ex40.py @@ -0,0 +1,9 @@ +# Scaled Jacobian + +# create mesh with volumes +from mechanic import * + +# get volumes with scaled jacobian > 0.75 +filter = smesh_builder.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_MoreThan, 0.75 ) +ids = mesh.GetIdsFromFilter(filter) +print("Number of volumes with scaled jacobian > 0.75:", len(ids)) diff --git a/doc/examples/quality_controls_ex24.py b/doc/examples/quality_controls_ex24.py new file mode 100644 index 000000000..3bce48801 --- /dev/null +++ b/doc/examples/quality_controls_ex24.py @@ -0,0 +1,24 @@ +# Scaled Jacobian + +from mechanic import * + +# Criterion : Scaled Jacobian > 0.75 +scaledJacobian = 0.75 + +aFilter = smesh_builder.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_MoreThan, scaledJacobian) + +anIds = mesh.GetIdsFromFilter(aFilter) + +# print the result +print("Criterion: Scaled Jacobian > ", scaledJacobian, " Nb = ", len(anIds)) +j = 1 +for i in range(len(anIds)): + if j > 20: j = 1; print("") + print(anIds[i], end=' ') + j = j + 1 + pass +print("") + +# create a group +aGroup = mesh.CreateEmptyGroup(SMESH.FACE, "Scaled Jacobian > " + repr(scaledJacobian)) +aGroup.Add(anIds) \ No newline at end of file diff --git a/doc/examples/tests.set b/doc/examples/tests.set index c52f32bdd..96acda0cb 100644 --- a/doc/examples/tests.set +++ b/doc/examples/tests.set @@ -73,6 +73,7 @@ SET(BAD_TESTS filters_ex36.py filters_ex37.py filters_ex38.py + filters_ex40.py filters_node_nb_conn.py filters_belong2group.py generate_flat_elements.py @@ -119,6 +120,7 @@ SET(BAD_TESTS quality_controls_ex20.py quality_controls_ex21.py quality_controls_ex22.py + quality_controls_ex24.py quality_controls_defl.py split_biquad.py transforming_meshes_ex01.py diff --git a/doc/gui/images/scaled_jacobian.png b/doc/gui/images/scaled_jacobian.png new file mode 100644 index 0000000000000000000000000000000000000000..6739c3121d1ed5a2cda5fe2d910b73a7d26f4fe6 GIT binary patch literal 2931 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 up!@v*Pv5{b)=q8k5`Z%>$5!dziT)>P!)(g{ literal 0 HcmV?d00001 diff --git a/doc/gui/images/scaled_jacobian_hexa.png b/doc/gui/images/scaled_jacobian_hexa.png new file mode 100644 index 0000000000000000000000000000000000000000..b05f8dc75ce08b533f7df355cfcd305b3e54d727 GIT binary patch literal 34875 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 DsElBa literal 0 HcmV?d00001 diff --git a/doc/gui/images/scaled_jacobian_tetra.png b/doc/gui/images/scaled_jacobian_tetra.png new file mode 100644 index 0000000000000000000000000000000000000000..5761c372f2f20cb4333848b25dd908ab22196338 GIT binary patch literal 34348 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 AJOBUy literal 0 HcmV?d00001 diff --git a/doc/gui/input/about_quality_controls.rst b/doc/gui/input/about_quality_controls.rst index 1e303af3e..7c7250b48 100644 --- a/doc/gui/input/about_quality_controls.rst +++ b/doc/gui/input/about_quality_controls.rst @@ -48,6 +48,7 @@ Volume quality controls: * :ref:`aspect_ratio_3d_page` * :ref:`volume_page` * :ref:`max_element_length_3d_page` +* :ref:`scaled_jacobian_page` * :ref:`bare_border_volumes_page` * :ref:`over_constrained_volumes_page` * :ref:`double_elements_page` @@ -99,4 +100,5 @@ To manage the quality controls call pop-up in the VTK viewer and select "Control max_element_length_3d.rst bare_border_volumes.rst over_constrained_volumes.rst - scalar_bar.rst + scalar_bar.rst + scaled_jacobian.rst \ No newline at end of file diff --git a/doc/gui/input/scaled_jacobian.rst b/doc/gui/input/scaled_jacobian.rst new file mode 100644 index 000000000..4ce8f9ac0 --- /dev/null +++ b/doc/gui/input/scaled_jacobian.rst @@ -0,0 +1,42 @@ +.. _scaled_jacobian_page: + +*************** +Scaled Jacobian +*************** + +The **Scaled Jacobian** mesh quality criteria, is a scalar measure of the deviation from the perfect element in the geometrical sense, this measure normalize the range of reported values +between [0,1] for a normal element, the value of 1 is considered a perfect element and 0 a element with a collapsed side. Negative values are also accepted for invalid elements. + +The **Scaled Jacobian** is implemented for volumetric elements returning 0 for polyhedrons. For tetrahedron and hexahedron the close form +is defined in `[1] `_, for pyramids the minimum scaled jacobian of the four tetrahedrons formed +in the four vertices of the pyramid base is reported, for pentahedrons a decomposition into tetrahedron is also done and finally for hexahedron prisms the minimum scaled jacobian between two pentahedrons and one hexahedron is reported. + +* Geometrically the Scaled Jacobian of a **tetrahedron** can be understood by the follow figure: + + .. image:: ../images/scaled_jacobian_tetra.png + :align: center + + The reported Scaled Jacobian will be 1 if :math:`\alpha=45^{\circ}` + +* For **hexadrons** this measure return 1 for the perfect non rotated elements: + + .. image:: ../images/scaled_jacobian_hexa.png + :align: center + + The reported Scaled Jacobian will be 1 if :math:`\alpha=0^{\circ}` for all the vertices + + +*To visualize the Scaled Jacobian quality criterion in your mesh:* + +.. |img| image:: ../images/scaled_jacobian.png + +#. Display your mesh in the viewer. +#. Choose **Controls > Volume Controls > Scaled Jacobian** or click *"Scaled Jacobian"* button |img| of the toolbar. + + Your mesh will be displayed in the viewer with its elements colored according to the applied mesh quality control criterion: + + .. image:: ../images/scaled_jacobian_mesh_tetra.png + :align: center + + +**See Also** a sample TUI Script of a :ref:`tui_scaled_jacobian` filter. diff --git a/doc/gui/input/tui_filters.rst b/doc/gui/input/tui_filters.rst index 0634328ae..314defd31 100644 --- a/doc/gui/input/tui_filters.rst +++ b/doc/gui/input/tui_filters.rst @@ -61,6 +61,24 @@ filters 3D mesh elements (volumes) according to the aspect ratio value: **See also:** :ref:`tui_aspect_ratio_3d` +.. _filter_scaled_jacobian: + +Scaled Jacobian +=============== + +filters 3D mesh elements (volumes) according to the scaled jacobian value: + +* element type is *SMESH.VOLUME* +* functor type is *SMESH.FT_ScaledJacobian* +* threshold is floating point value + +.. literalinclude:: ../../examples/filters_ex40.py + :language: python + +:download:`Download this script <../../examples/filters_ex40.py>` + +**See also:** :ref:`tui_scaled_jacobian` + .. _filter_warping_angle: Warping angle diff --git a/doc/gui/input/tui_quality_controls.rst b/doc/gui/input/tui_quality_controls.rst index 5a331a1f4..69d770493 100644 --- a/doc/gui/input/tui_quality_controls.rst +++ b/doc/gui/input/tui_quality_controls.rst @@ -240,3 +240,13 @@ Element Diameter 3D :language: python :download:`Download this script <../../examples/quality_controls_ex22.py>` + +.. _tui_scaled_jacobian: + +Scaled Jacobian +=================== + +.. literalinclude:: ../../examples/quality_controls_ex24.py + :language: python + +:download:`Download this script <../../examples/quality_controls_ex24.py>` diff --git a/idl/SMESH_Filter.idl b/idl/SMESH_Filter.idl index e4dddba85..51246e0d3 100644 --- a/idl/SMESH_Filter.idl +++ b/idl/SMESH_Filter.idl @@ -47,7 +47,8 @@ module SMESH FT_Taper, FT_Skew, FT_Area, - FT_Volume3D, + FT_Volume3D, + FT_ScaledJacobian, FT_MaxElementLength2D, FT_MaxElementLength3D, FT_FreeBorders, @@ -170,6 +171,7 @@ module SMESH }; interface BallDiameter : NumericalFunctor{}; interface NodeConnectivityNumber : NumericalFunctor{}; + interface ScaledJacobian : NumericalFunctor{}; /*! @@ -598,6 +600,7 @@ module SMESH MultiConnection2D CreateMultiConnection2D(); BallDiameter CreateBallDiameter(); NodeConnectivityNumber CreateNodeConnectivityNumber(); + ScaledJacobian CreateScaledJacobian(); /*! * Create logical functors ( predicates ) */ diff --git a/resources/mesh_scaled_jacobian.png b/resources/mesh_scaled_jacobian.png new file mode 100644 index 0000000000000000000000000000000000000000..0f01f54a511ac23d231a9513eab0f0cd44e1bc9d GIT binary patch literal 7383 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 literal 0 HcmV?d00001 diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 692c52dae..229162e3e 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -2351,6 +2351,70 @@ SMDSAbs_ElementType NodeConnectivityNumber::GetType() const return SMDSAbs_Node; } +//================================================================================ +/* + Class : ScaledJacobian + Description : Functor returning the ScaledJacobian for volumetric elements +*/ +//================================================================================ + +double ScaledJacobian::GetValue( long theElementId ) +{ + if ( theElementId && myMesh ) { + SMDS_VolumeTool aVolumeTool; + if ( aVolumeTool.Set( myMesh->FindElement( theElementId ))) + return aVolumeTool.GetScaledJacobian(); + } + return 0; + + /* + //VTK version not used because lack of implementation for HEXAGONAL_PRISM. + //Several mesh quality measures implemented in vtkMeshQuality can be accessed left here as reference + double aVal = 0; + myCurrElement = myMesh->FindElement( theElementId ); + if ( myCurrElement ) + { + VTKCellType cellType = myCurrElement->GetVtkType(); + vtkUnstructuredGrid* grid = const_cast( myMesh )->GetGrid(); + vtkCell* avtkCell = grid->GetCell( myCurrElement->GetVtkID() ); + switch ( cellType ) + { + case VTK_QUADRATIC_TETRA: + case VTK_TETRA: + aVal = Round( vtkMeshQuality::TetScaledJacobian( avtkCell )); + break; + case VTK_QUADRATIC_HEXAHEDRON: + case VTK_HEXAHEDRON: + aVal = Round( vtkMeshQuality::HexScaledJacobian( avtkCell )); + break; + case VTK_QUADRATIC_WEDGE: + case VTK_WEDGE: //Pentahedron + aVal = Round( vtkMeshQuality::WedgeScaledJacobian( avtkCell )); + break; + case VTK_QUADRATIC_PYRAMID: + case VTK_PYRAMID: + aVal = Round( vtkMeshQuality::PyramidScaledJacobian( avtkCell )); + break; + case VTK_HEXAGONAL_PRISM: + case VTK_POLYHEDRON: + default: + break; + } + } + return aVal; + */ +} + +double ScaledJacobian::GetBadRate( double Value, int /*nbNodes*/ ) const +{ + return Value; +} + +SMDSAbs_ElementType ScaledJacobian::GetType() const +{ + return SMDSAbs_Volume; +} + /* PREDICATES */ diff --git a/src/Controls/SMESH_ControlsDef.hxx b/src/Controls/SMESH_ControlsDef.hxx index 3bfc2da2c..d6330024e 100644 --- a/src/Controls/SMESH_ControlsDef.hxx +++ b/src/Controls/SMESH_ControlsDef.hxx @@ -404,6 +404,17 @@ namespace SMESH{ virtual double GetBadRate( double Value, int nbNodes ) const; virtual SMDSAbs_ElementType GetType() const; }; + + /* + Class : ScaledJacobian + Description : Functor returning the ScaledJacobian as implemeted in VTK for volumetric elements + */ + class SMESHCONTROLS_EXPORT ScaledJacobian: public virtual NumericalFunctor{ + public: + virtual double GetValue( long theNodeId ); + virtual double GetBadRate( double Value, int nbNodes ) const; + virtual SMDSAbs_ElementType GetType() const; + }; /* diff --git a/src/OBJECT/SMESH_Actor.cxx b/src/OBJECT/SMESH_Actor.cxx index e4e50c362..6bab6722f 100644 --- a/src/OBJECT/SMESH_Actor.cxx +++ b/src/OBJECT/SMESH_Actor.cxx @@ -953,6 +953,14 @@ void SMESH_ActorDef::SetControlMode( eControl theMode, bool theCheckEntityMode ) myControlActor = my3DActor; break; } + case eScaledJacobian: + { + SMESH::Controls::ScaledJacobian* aControl = new SMESH::Controls::ScaledJacobian(); + aControl->SetPrecision( myControlsPrecision ); + myFunctor.reset( aControl ); + myControlActor = my3DActor; + break; + } case eMaxElementLength2D: { SMESH::Controls::MaxElementLength2D* aControl = new SMESH::Controls::MaxElementLength2D(); @@ -1112,7 +1120,6 @@ void SMESH_ActorDef::SetControlMode( eControl theMode, bool theCheckEntityMode ) QString aTitle = QString(myScalarBarActor->GetTitle()); aTitle.replace(QRegExp("(:\\s).*"),"\\1"+ QString::number(GetNumberControlEntities())); myScalarBarActor->SetTitle(aTitle.toUtf8().constData()); - } else { if(theCheckEntityMode){ diff --git a/src/OBJECT/SMESH_Actor.h b/src/OBJECT/SMESH_Actor.h index 2fcfa3c4c..c9a5fd597 100644 --- a/src/OBJECT/SMESH_Actor.h +++ b/src/OBJECT/SMESH_Actor.h @@ -139,7 +139,7 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor enum eControl{eNone, eLength, eLength2D, eDeflection2D, eFreeBorders, eFreeEdges, eFreeNodes, eFreeFaces, eMultiConnection, eArea, eTaper, eAspectRatio, - eMinimumAngle, eWarping, eSkew, eAspectRatio3D, eMultiConnection2D, eVolume3D, + eMinimumAngle, eWarping, eSkew, eAspectRatio3D, eMultiConnection2D, eVolume3D, eScaledJacobian, eMaxElementLength2D, eMaxElementLength3D, eBareBorderFace, eBareBorderVolume, eOverConstrainedFace, eOverConstrainedVolume, eCoincidentNodes, eCoincidentElems1D, eCoincidentElems2D, eCoincidentElems3D, eNodeConnectivityNb, diff --git a/src/SMDS/SMDS_VolumeTool.cxx b/src/SMDS/SMDS_VolumeTool.cxx index 23bff3b88..c3b9ef30f 100644 --- a/src/SMDS/SMDS_VolumeTool.cxx +++ b/src/SMDS/SMDS_VolumeTool.cxx @@ -80,9 +80,17 @@ static int Tetra_RE [4][4] = { // REVERSED -> FORWARD (EXTERNAL) { 0, 3, 2, 0 }}; static int Tetra_nbN [] = { 3, 3, 3, 3 }; -// -// PYRAMID -// +/* +// N1 +---------+ N2 +// | \ / | +// | \ / | +// | \ / | +// | /+\ | PYRAMID +// | / N4\ | +// | / \ | +// |/ \| +// N0 +---------+ N3 +*/ static int Pyramid_F [5][5] = { // FORWARD == EXTERNAL { 0, 1, 2, 3, 0 }, // All faces have external normals { 0, 4, 1, 0, 4 }, @@ -363,13 +371,18 @@ struct XYZ { inline XYZ operator-( const XYZ& other ); inline XYZ operator+( const XYZ& other ); inline XYZ Crossed( const XYZ& other ); + inline XYZ operator-(); inline double Dot( const XYZ& other ); inline double Magnitude(); inline double SquareMagnitude(); + inline XYZ Normalize(); }; inline XYZ XYZ::operator-( const XYZ& Right ) { return XYZ(x - Right.x, y - Right.y, z - Right.z); } +inline XYZ XYZ::operator-() { + return XYZ(-x,-y,-z); +} inline XYZ XYZ::operator+( const XYZ& Right ) { return XYZ(x + Right.x, y + Right.y, z + Right.z); } @@ -387,6 +400,13 @@ inline double XYZ::Magnitude() { inline double XYZ::SquareMagnitude() { return (x * x + y * y + z * z); } +inline XYZ XYZ::Normalize() { + double magnitude = Magnitude(); + if ( magnitude != 0.0 ) + return XYZ(x /= magnitude,y /= magnitude,z /= magnitude ); + else + return XYZ(x,y,z); +} //================================================================================ /*! @@ -694,7 +714,6 @@ static double getTetraVolume(const SMDS_MeshNode* n1, //function : GetSize //purpose : Return element volume //======================================================================= - double SMDS_VolumeTool::GetSize() const { double V = 0.; @@ -847,6 +866,334 @@ double SMDS_VolumeTool::GetSize() const return V; } + +//======================================================================= +//function : getTetraScaledJacobian +//purpose : Given the smesh nodes in the canonical order of the tetrahedron, return the scaled jacobian +//======================================================================= +static double getTetraScaledJacobian(const SMDS_MeshNode* n0, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3) +{ + const double sqrt = std::sqrt(2.0); + // Get the coordinates + XYZ p0( n0 ); + XYZ p1( n1 ); + XYZ p2( n2 ); + XYZ p3( n3 ); + // Define the edges connecting the nodes + XYZ L0 = p1-p0; + XYZ L1 = p2-p1; + XYZ L2 = p2-p0; // invert the definition of doc to get the proper orientation of the crossed product + XYZ L3 = p3-p0; + XYZ L4 = p3-p1; + XYZ L5 = p3-p2; + double Jacobian = L2.Crossed( L0 ).Dot( L3 ); + double norm0 = L0.Magnitude(); + double norm1 = L1.Magnitude(); + double norm2 = L2.Magnitude(); + double norm3 = L3.Magnitude(); + double norm4 = L4.Magnitude(); + double norm5 = L5.Magnitude(); + + std::array norms{}; + norms[0] = Jacobian; + norms[1] = norm3*norm4*norm5; + norms[2] = norm1*norm2*norm5; + norms[3] = norm0*norm1*norm4; + norms[4] = norm0*norm2*norm3; + + auto findMaxNorm = std::max_element(norms.begin(), norms.end()); + double maxNorm = *findMaxNorm; + + if ( std::fabs( maxNorm ) < std::numeric_limits::min() ) + maxNorm = std::numeric_limits::max(); + + return Jacobian * sqrt / maxNorm; +} + +//======================================================================= +//function : getPyramidScaledJacobian +//purpose : Given the pyramid, compute the scaled jacobian of the four tetrahedrons and return the minimun value. +//======================================================================= +static double getPyramidScaledJacobian(const SMDS_MeshNode* n0, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4) +{ + const double sqrt = std::sqrt(2.0); + std::array tetScaledJacobian{}; + tetScaledJacobian[0] = getTetraScaledJacobian(n0, n1, n3, n4); + tetScaledJacobian[1] = getTetraScaledJacobian(n1, n2, n0, n4); + tetScaledJacobian[2] = getTetraScaledJacobian(n2, n3, n1, n4); + tetScaledJacobian[3] = getTetraScaledJacobian(n3, n0, n2, n4); + + auto minEntry = std::min_element(tetScaledJacobian.begin(), tetScaledJacobian.end()); + + double scaledJacobian = (*minEntry) * 2.0/sqrt; + return scaledJacobian < 1.0 ? scaledJacobian : 1.0 - (scaledJacobian - 1.0); +} + + + +//======================================================================= +//function : getHexaScaledJacobian +//purpose : Evaluate the scaled jacobian on the eight vertices of the hexahedron and return the minimal registered value +//remark : Follow the reference numeration described at the top of the class. +//======================================================================= +static double getHexaScaledJacobian(const SMDS_MeshNode* n0, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5, + const SMDS_MeshNode* n6, + const SMDS_MeshNode* n7) +{ + // Scaled jacobian is an scalar quantity measuring the deviation of the geometry from the perfect geometry + // Get the coordinates + XYZ p0( n0 ); + XYZ p1( n1 ); + XYZ p2( n2 ); + XYZ p3( n3 ); + XYZ p4( n4 ); + XYZ p5( n5 ); + XYZ p6( n6 ); + XYZ p7( n7 ); + + // Define the edges connecting the nodes + XYZ L0 = (p1-p0).Normalize(); + XYZ L1 = (p2-p1).Normalize(); + XYZ L2 = (p3-p2).Normalize(); + XYZ L3 = (p3-p0).Normalize(); + XYZ L4 = (p4-p0).Normalize(); + XYZ L5 = (p5-p1).Normalize(); + XYZ L6 = (p6-p2).Normalize(); + XYZ L7 = (p7-p3).Normalize(); + XYZ L8 = (p5-p4).Normalize(); + XYZ L9 = (p6-p5).Normalize(); + XYZ L10 = (p7-p6).Normalize(); + XYZ L11 = (p7-p4).Normalize(); + XYZ X0 = (p1-p0+p2-p3+p6-p7+p5-p4).Normalize(); + XYZ X1 = (p3-p0+p2-p1+p7-p4+p6-p5).Normalize(); + XYZ X2 = (p4-p0+p7-p3+p5-p1+p6-p2).Normalize(); + + std::array scaledJacobian{}; + //Scaled jacobian of nodes following their numeration + scaledJacobian[0] = L4.Crossed( L3).Dot( L0 ); // For L0 + scaledJacobian[1] = L5.Crossed(-L0).Dot( L1 ); // For L1 + scaledJacobian[2] = L6.Crossed(-L1).Dot( L2 ); // For L2 + scaledJacobian[3] = L7.Crossed(-L2).Dot(-L3 ); // For L3 + scaledJacobian[4] = -L4.Crossed( L8).Dot( L11 ); // For L11 + scaledJacobian[5] = -L5.Crossed( L9).Dot(-L8 ); // For L8 + scaledJacobian[6] = -L6.Crossed(L10).Dot(-L9 ); // For L9 + scaledJacobian[7] = -L7.Crossed(-L11).Dot(-L10 ); // For L10 + scaledJacobian[8] = X2.Crossed( X1).Dot( X0 ); // For principal axes + + auto minScaledJacobian = std::min_element(scaledJacobian.begin(), scaledJacobian.end()); + return *minScaledJacobian; +} + + +//======================================================================= +//function : getTetraNormalizedJacobian +//purpose : Return the jacobian of the tetrahedron based on normalized vectors +//======================================================================= +static double getTetraNormalizedJacobian(const SMDS_MeshNode* n0, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3) +{ + const double sqrt = std::sqrt(2.0); + // Get the coordinates + XYZ p0( n0 ); + XYZ p1( n1 ); + XYZ p2( n2 ); + XYZ p3( n3 ); + // Define the normalized edges connecting the nodes + XYZ L0 = (p1-p0).Normalize(); + XYZ L2 = (p2-p0).Normalize(); // invert the definition of doc to get the proper orientation of the crossed product + XYZ L3 = (p3-p0).Normalize(); + return L2.Crossed( L0 ).Dot( L3 ); +} + +//======================================================================= +//function : getPentaScaledJacobian +//purpose : Evaluate the scaled jacobian on the pentahedron based on decomposed tetrahedrons +//======================================================================= +/* +// + N1 +// /|\ +// / | \ +// / | \ +// / | \ +// N0 +---------+ N2 +// | | | NUMERATION RERENCE FOLLOWING POSSITIVE RIGHT HAND RULE +// | + N4 | +// | / \ | PENTAHEDRON +// | / \ | +// | / \ | +// |/ \| +// N3 +---------+ N5 +// +// N1 +// + +// |\ +// /| \ +// / | \ +// N0 +--|---+ N2 TETRAHEDRON ASSOCIATED TO N0 +// \ | / Numeration passed to getTetraScaledJacobian +// \ | / N0=N0; N1=N2; N2=N3; N3=N1 +// \| / +// |/ +// + +// N3 +// +// N1 +// + +// /|\ +// / | \ +// / | \ +// N2 +---|---+ N5 TETRAHEDRON ASSOCIATED TO N2 +// \ | / Numeration passed to getTetraScaledJacobian +// \ | / N0=N2; N1=N5; N2=N0; N3=N1 +// \ |/ +// \| +// + +// N0 +// +// N4 +// + +// /|\ +// / | \ +// / | \ +// N3 +---|---+ N0 TETRAHEDRON ASSOCIATED TO N3 +// \ | / Numeration passed to getTetraScaledJacobian +// \ | / N0=N3; N1=N0; N2=N5; N3=N4 +// \ | / +// \|/ +// + +// N5 +// +// N3 +// + +// /|\ +// / | \ +// / | \ +// N1 +---|---+ N2 TETRAHEDRON ASSOCIATED TO N1 +// \ | / Numeration passed to getTetraScaledJacobian +// \ | / N0=N1; N1=N2; N2=N0; N3=N3 +// \ | / +// \|/ +// + +// N0 +// +// ... +*/ +static double getPentaScaledJacobian(const SMDS_MeshNode* n0, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5) +{ + std::array scaledJacobianOfReferenceTetra{}; + scaledJacobianOfReferenceTetra[0] = getTetraNormalizedJacobian(n0, n2, n3, n1); // For n0 + scaledJacobianOfReferenceTetra[1] = getTetraNormalizedJacobian(n2, n5, n0, n1); // For n2 + scaledJacobianOfReferenceTetra[2] = getTetraNormalizedJacobian(n3, n0, n5, n4); // For n3 + scaledJacobianOfReferenceTetra[3] = getTetraNormalizedJacobian(n5, n3, n2, n4); // For n5 + scaledJacobianOfReferenceTetra[4] = getTetraNormalizedJacobian(n1, n2, n0, n3); // For n1 + scaledJacobianOfReferenceTetra[5] = getTetraNormalizedJacobian(n4, n3, n5, n2); // For n4 + + auto minScaledJacobian = std::min_element(scaledJacobianOfReferenceTetra.begin(), scaledJacobianOfReferenceTetra.end()); + double minScalJac = (*minScaledJacobian)* 2.0 / std::sqrt(3.0); + + if (minScalJac > 0) + return std::min(minScalJac, std::numeric_limits::max()); + + return std::max(minScalJac, -std::numeric_limits::max()); +} + +//======================================================================= +//function : getHexaPrismScaledJacobian +//purpose : Evaluate the scaled jacobian on the hexaprism by decomposing the goemetry into three 1hexa + 2 pentahedrons +//======================================================================= +static double getHexaPrismScaledJacobian(const SMDS_MeshNode* n0, + const SMDS_MeshNode* n1, + const SMDS_MeshNode* n2, + const SMDS_MeshNode* n3, + const SMDS_MeshNode* n4, + const SMDS_MeshNode* n5, + const SMDS_MeshNode* n6, + const SMDS_MeshNode* n7, + const SMDS_MeshNode* n8, + const SMDS_MeshNode* n9, + const SMDS_MeshNode* n10, + const SMDS_MeshNode* n11) +{ + // The Pentahedron from the left + // n0=n0; n1=n1; n2=n2; n3=n6; n4=n7, n5=n8; + double scaledJacobianPentleft = getPentaScaledJacobian( n0, n1, n2, n6, n7, n8 ); + // The core Hexahedron + // n0=n0; n1=n2, n2=n3; n3=n5; n4=n6; n5=n8; n6=n9; n7=n11 + double scaledJacobianHexa = getHexaScaledJacobian( n0, n2, n3, n5, n6, n8, n9, n11 ); + // The Pentahedron from the right + // n0=n5; n1=n4; n2=n3; n3=n11; n4=n10; n5=n9 + double scaledJacobianPentright = getPentaScaledJacobian( n5, n4, n3, n11, n10, n9 ); + + return std::min( scaledJacobianHexa, std::min( scaledJacobianPentleft, scaledJacobianPentright ) ); + +} + +//======================================================================= +//function : GetScaledJacobian +//purpose : Return element Scaled Jacobian using the generic definition given +// in https://gitlab.kitware.com/third-party/verdict/-/blob/master/SAND2007-2853p.pdf +//======================================================================= + +double SMDS_VolumeTool::GetScaledJacobian() const +{ + + // For Tetra, call directly the getTetraScaledJacobian + double scaledJacobian = 0.; + + VolumeType type = GetVolumeType(); + switch (type) + { + case TETRA: + case QUAD_TETRA: + scaledJacobian = getTetraScaledJacobian( myVolumeNodes[0], myVolumeNodes[1], myVolumeNodes[2], myVolumeNodes[3] ); + break; + case HEXA: + case QUAD_HEXA: + scaledJacobian = getHexaScaledJacobian( myVolumeNodes[0], myVolumeNodes[1], myVolumeNodes[2], myVolumeNodes[3], + myVolumeNodes[4], myVolumeNodes[5], myVolumeNodes[6], myVolumeNodes[7] ); + break; + case PYRAM: + case QUAD_PYRAM: + scaledJacobian = getPyramidScaledJacobian( myVolumeNodes[0], myVolumeNodes[1], myVolumeNodes[2], myVolumeNodes[3], myVolumeNodes[4] ); + break; + case PENTA: + case QUAD_PENTA: + scaledJacobian = getPentaScaledJacobian( myVolumeNodes[0], myVolumeNodes[1], + myVolumeNodes[2], myVolumeNodes[3], + myVolumeNodes[4], myVolumeNodes[5] ); + break; + case HEX_PRISM: + scaledJacobian = getHexaPrismScaledJacobian( myVolumeNodes[0], myVolumeNodes[1], myVolumeNodes[2], myVolumeNodes[3], + myVolumeNodes[4], myVolumeNodes[5], myVolumeNodes[6], myVolumeNodes[7], + myVolumeNodes[8], myVolumeNodes[9], myVolumeNodes[10], myVolumeNodes[11]); + break; + default: + break; + } + + return scaledJacobian; +} + + //======================================================================= //function : GetBaryCenter //purpose : diff --git a/src/SMDS/SMDS_VolumeTool.hxx b/src/SMDS/SMDS_VolumeTool.hxx index 8e34c0a27..0db821edb 100644 --- a/src/SMDS/SMDS_VolumeTool.hxx +++ b/src/SMDS/SMDS_VolumeTool.hxx @@ -103,6 +103,9 @@ class SMDS_EXPORT SMDS_VolumeTool double GetSize() const; // Return element volume + double GetScaledJacobian() const; + // Return the scaled jacobian + bool GetBaryCenter (double & X, double & Y, double & Z) const; bool IsOut(double X, double Y, double Z, double tol) const; diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index 324705c87..85ab20cc9 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -1162,6 +1162,8 @@ namespace type = QObject::tr( "EQUAL_VOLUME" ); else if ( dynamic_cast< SMESH::Controls::NodeConnectivityNumber* >( f.get() ) ) type = QObject::tr( "NODE_CONNECTIVITY_NB" ); + else if ( dynamic_cast< SMESH::Controls::ScaledJacobian* >( f.get() ) ) + type = QObject::tr( "SCALED_JACOBIAN" ); return type; } @@ -1778,6 +1780,7 @@ namespace ActionControl.Bind( SMESHOp::OpEqualFace, SMESH_Actor::eCoincidentElems2D ); ActionControl.Bind( SMESHOp::OpAspectRatio3D, SMESH_Actor::eAspectRatio3D ); ActionControl.Bind( SMESHOp::OpVolume, SMESH_Actor::eVolume3D ); + ActionControl.Bind( SMESHOp::OpScaledJacobian, SMESH_Actor::eScaledJacobian ); ActionControl.Bind( SMESHOp::OpMaxElementLength3D, SMESH_Actor::eMaxElementLength3D ); ActionControl.Bind( SMESHOp::OpBareBorderVolume, SMESH_Actor::eBareBorderVolume ); ActionControl.Bind( SMESHOp::OpOverConstrainedVolume, SMESH_Actor::eOverConstrainedVolume ); @@ -3902,6 +3905,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case SMESHOp::OpEqualFace: case SMESHOp::OpAspectRatio3D: case SMESHOp::OpVolume: + case SMESHOp::OpScaledJacobian: case SMESHOp::OpMaxElementLength3D: case SMESHOp::OpBareBorderVolume: case SMESHOp::OpOverConstrainedVolume: @@ -4213,6 +4217,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( SMESHOp::OpBareBorderVolume, "BARE_BORDER_VOLUME", "ICON_BARE_BORDER_VOLUME", 0, true ); createSMESHAction( SMESHOp::OpOverConstrainedVolume, "OVER_CONSTRAINED_VOLUME", "ICON_OVER_CONSTRAINED_VOLUME", 0, true ); createSMESHAction( SMESHOp::OpEqualVolume, "EQUAL_VOLUME", "ICON_EQUAL_VOLUME", 0, true ); + createSMESHAction( SMESHOp::OpScaledJacobian, "SCALED_JACOBIAN", "ICON_SCALED_JACOBIAN", 0, true ); createSMESHAction( SMESHOp::OpOverallMeshQuality, "OVERALL_MESH_QUALITY", "ICON_OVL_MESH_QUALITY" ); createSMESHAction( SMESHOp::OpNode, "NODE", "ICON_DLG_NODE" ); @@ -4353,7 +4358,7 @@ void SMESHGUI::initialize( CAM_Application* app ) << SMESHOp::OpOverConstrainedFace << SMESHOp::OpEqualFace // face controls << SMESHOp::OpAspectRatio3D << SMESHOp::OpVolume << SMESHOp::OpMaxElementLength3D << SMESHOp::OpBareBorderVolume - << SMESHOp::OpOverConstrainedVolume << SMESHOp::OpEqualVolume; // volume controls + << SMESHOp::OpOverConstrainedVolume << SMESHOp::OpEqualVolume << SMESHOp::OpScaledJacobian; // volume controls QActionGroup* aCtrlGroup = new QActionGroup( application()->desktop() ); aCtrlGroup->setExclusive( true ); for( int i = 0; i < aCtrlActions.size(); i++ ) @@ -4469,6 +4474,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( SMESHOp::OpBareBorderVolume, volumeId, -1 ); createMenu( SMESHOp::OpOverConstrainedVolume, volumeId, -1 ); createMenu( SMESHOp::OpEqualVolume, volumeId, -1 ); + createMenu( SMESHOp::OpScaledJacobian, volumeId, -1 ); createMenu( separator(), ctrlId, -1 ); createMenu( SMESHOp::OpReset, ctrlId, -1 ); createMenu( separator(), ctrlId, -1 ); @@ -4626,6 +4632,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( SMESHOp::OpBareBorderVolume, ctrl3dTb ); createTool( SMESHOp::OpOverConstrainedVolume, ctrl3dTb ); createTool( SMESHOp::OpEqualVolume, ctrl3dTb ); + createTool( SMESHOp::OpScaledJacobian, ctrl3dTb ); int addElemTb = createTool( tr( "TB_ADD" ), QString( "SMESHAddElementToolbar" ) ) ; createTool( SMESHOp::OpNode, addElemTb ); @@ -5103,6 +5110,10 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->setRule( action( SMESHOp::OpEqualVolume ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( SMESHOp::OpEqualVolume ), "controlMode = 'eCoincidentElems3D'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert ( action( SMESHOp::OpScaledJacobian ), aSubId, -1 ); + popupMgr()->setRule( action( SMESHOp::OpScaledJacobian ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( SMESHOp::OpScaledJacobian ), "controlMode = 'eScaledJacobian'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert( separator(), anId, -1 ); popupMgr()->insert( action( SMESHOp::OpShowScalarBar ), anId, -1 ); diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index d97e2e7f5..a475655d9 100644 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -1568,6 +1568,7 @@ void SMESHGUI_FilterTable::updateAdditionalWidget() aCriterion == SMESH::FT_Skew || aCriterion == SMESH::FT_Area || aCriterion == SMESH::FT_Volume3D || + aCriterion == SMESH::FT_ScaledJacobian || aCriterion == SMESH::FT_MaxElementLength2D || aCriterion == SMESH::FT_MaxElementLength3D || aCriterion == SMESH::FT_Length || @@ -1816,6 +1817,7 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int /*col*/, case SMESH::FT_Skew: case SMESH::FT_Area: case SMESH::FT_Volume3D: + case SMESH::FT_ScaledJacobian: case SMESH::FT_MaxElementLength2D: case SMESH::FT_MaxElementLength3D: anIsDoubleCriterion = true; break; @@ -2284,6 +2286,7 @@ const QMap& SMESHGUI_FilterTable::getCriteria (const int theType) aCriteria[ SMESH::FT_EqualVolumes ] = tr("EQUAL_VOLUME"); aCriteria[ SMESH::FT_EntityType ] = tr("ENTITY_TYPE"); aCriteria[ SMESH::FT_ConnectedElements ] = tr("CONNECTED_ELEMS"); + aCriteria[ SMESH::FT_ScaledJacobian ] = tr("SCALED_JACOBIAN"); } return aCriteria; } diff --git a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx index f7d237098..a0ad87dc5 100644 --- a/src/SMESHGUI/SMESHGUI_MeshInfo.cxx +++ b/src/SMESHGUI/SMESHGUI_MeshInfo.cxx @@ -1684,6 +1684,8 @@ QString SMESHGUI_ElemInfo::ctrl2str( int control ) title = tr( "AREA_ELEMENTS" ); break; case SMESH::FT_Volume3D: title = tr( "VOLUME_3D_ELEMENTS" ); break; + case SMESH::FT_ScaledJacobian: + title = tr( "SCALED_JACOBIAN" ); break; case SMESH::FT_MaxElementLength2D: title = tr( "MAX_ELEMENT_LENGTH_2D" ); break; case SMESH::FT_MaxElementLength3D: diff --git a/src/SMESHGUI/SMESHGUI_Operations.h b/src/SMESHGUI/SMESHGUI_Operations.h index a2f2623ae..ca7d9202d 100644 --- a/src/SMESHGUI/SMESHGUI_Operations.h +++ b/src/SMESHGUI/SMESHGUI_Operations.h @@ -122,6 +122,7 @@ namespace SMESHOp { OpBareBorderVolume = 3303, // MENU CONTROLS - VOLUMES WITH BARE BORDER OpOverConstrainedVolume = 3304, // MENU CONTROLS - OVERCONSTRAINED VOLUMES OpEqualVolume = 3305, // MENU CONTROLS - DOUBLE VOLUMES + OpScaledJacobian = 3306, // MENU CONTROLS - SCALED JACOBIAN OpOverallMeshQuality = 3400, // MENU CONTROLS - OVERALL MESH QUALITY // Modification -------------------//-------------------------------- OpNode = 4000, // MENU MODIFICATION - ADD - NODE diff --git a/src/SMESHGUI/SMESHGUI_Selection.cxx b/src/SMESHGUI/SMESHGUI_Selection.cxx index 4f9fa8da2..837ae324d 100644 --- a/src/SMESHGUI/SMESHGUI_Selection.cxx +++ b/src/SMESHGUI/SMESHGUI_Selection.cxx @@ -371,6 +371,7 @@ QString SMESHGUI_Selection::controlMode( int ind ) const case SMESH_Actor::eMultiConnection2D: mode = "eMultiConnection2D"; break; case SMESH_Actor::eArea: mode = "eArea"; break; case SMESH_Actor::eVolume3D: mode = "eVolume3D"; break; + case SMESH_Actor::eScaledJacobian: mode = "eScaledJacobian"; break; case SMESH_Actor::eMaxElementLength2D: mode = "eMaxElementLength2D"; break; case SMESH_Actor::eMaxElementLength3D: mode = "eMaxElementLength3D"; break; case SMESH_Actor::eTaper: mode = "eTaper"; break; @@ -429,6 +430,7 @@ bool SMESHGUI_Selection::isNumFunctor( int ind ) const case SMESH_Actor::eMultiConnection2D: case SMESH_Actor::eArea: case SMESH_Actor::eVolume3D: + case SMESH_Actor::eScaledJacobian: case SMESH_Actor::eMaxElementLength2D: case SMESH_Actor::eMaxElementLength3D: case SMESH_Actor::eTaper: diff --git a/src/SMESHGUI/SMESHGUI_SelectionProxy.cxx b/src/SMESHGUI/SMESHGUI_SelectionProxy.cxx index edc614aae..da5d3e346 100644 --- a/src/SMESHGUI/SMESHGUI_SelectionProxy.cxx +++ b/src/SMESHGUI/SMESHGUI_SelectionProxy.cxx @@ -941,6 +941,9 @@ bool SMESH::SelectionProxy::elementControl( int id, int control, double precisio case SMESH::FT_BallDiameter: functor.reset( new SMESH::Controls::BallDiameter() ); break; + case SMESH::FT_ScaledJacobian: + functor.reset( new SMESH::Controls::ScaledJacobian() ); + break; default: break; } @@ -1009,6 +1012,9 @@ bool SMESH::SelectionProxy::elementControl( int id, int control, double precisio case SMESH::FT_BallDiameter: functor = manager->CreateBallDiameter(); break; + case SMESH::FT_ScaledJacobian: + functor = manager->CreateScaledJacobian(); + break; default: break; } diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index fc90e47de..4bc52c55e 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -611,6 +611,10 @@ ICON_VOLUME_3D mesh_volume_3d.png + + ICON_SCALED_JACOBIAN + mesh_scaled_jacobian.png + ICON_BARE_BORDER_VOLUME bare_border_volume.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index fb04b585c..084780493 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -95,6 +95,10 @@ BARE_BORDER_VOLUME Volumes with bare border + + SCALED_JACOBIAN + Scaled Jacobian + OVER_CONSTRAINED_VOLUME Over-constrained volumes @@ -1316,6 +1320,10 @@ MEN_VOLUME_3D Volume + + MEN_SCALED_JACOBIAN + Scaled Jacobian + MEN_WARP Warping Angle @@ -3912,6 +3920,10 @@ Use Display Entity menu command to show them. STB_VOLUME_3D Volume + + STB_SCALED_JACOBIAN + Scaled Jacobian + STB_WARP Warping angle @@ -4624,6 +4636,10 @@ Use Display Entity menu command to show them. TOP_VOLUME_3D Volume + + TOP_SCALED_JACOBIAN + Scaled Jacobian + TOP_WARP Warping angle @@ -6496,6 +6512,10 @@ Please enter correct value and try again VOLUME_3D Volume + + SCALED_JACOBIAN + Scaled Jacobian + WARPING Warping diff --git a/src/SMESHGUI/SMESH_msg_fr.ts b/src/SMESHGUI/SMESH_msg_fr.ts index 7fe5b7096..01a861c32 100644 --- a/src/SMESHGUI/SMESH_msg_fr.ts +++ b/src/SMESHGUI/SMESH_msg_fr.ts @@ -99,6 +99,10 @@ OVER_CONSTRAINED_VOLUME Volumes sur-contraints + + SCALED_JACOBIAN + Jacobien normalisé + MIN_DIAG_ELEMENTS Diagonale minimum @@ -1316,6 +1320,10 @@ MEN_VOLUME_3D Volume + + MEN_SCALED_JACOBIAN + Jacobien normalisé + MEN_WARP Angle de déformation @@ -3911,6 +3919,10 @@ Utilisez le menu "Visualiser une entité" pour les afficher. STB_VOLUME_3D Volume + + STB_SCALED_JACOBIAN + Jacobien normalisé + STB_WARP Angle de déformation @@ -4623,6 +4635,10 @@ Utilisez le menu "Visualiser une entité" pour les afficher. TOP_VOLUME_3D Volume + + TOP_SCALED_JACOBIAN + Jacobien normalisé + TOP_WARP Angle de déformation diff --git a/src/SMESHGUI/SMESH_msg_ja.ts b/src/SMESHGUI/SMESH_msg_ja.ts index 01277cbd8..07b8fcef0 100644 --- a/src/SMESHGUI/SMESH_msg_ja.ts +++ b/src/SMESHGUI/SMESH_msg_ja.ts @@ -71,6 +71,10 @@ NODE_CONNECTIVITY_NB 節点接続番号 + + SCALED_JACOBIAN + スケーリングされたヤコビアン + FREE_EDGES フリーエッジ @@ -1119,6 +1123,10 @@ MEN_VOLUME_3D ボリューム + + MEN_SCALED_JACOBIAN + スケーリングされたヤコビアン + MEN_WARP 変形の角度 @@ -3519,6 +3527,10 @@ STB_VOLUMES ボリューム + + STB_SCALED_JACOBIAN + スケーリングされたヤコビアン + STB_VOLUME_3D ボリューム @@ -4183,6 +4195,10 @@ TOP_VOLUMES ボリューム + + TOP_SCALED_JACOBIAN + スケーリングされたヤコビアン + TOP_VOLUME_3D ボリューム @@ -5921,7 +5937,7 @@ VOLUME_3D - ボリューム + スケーリングされたヤコビアン WARPING diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 7a45a8e7f..f35798fff 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -301,6 +301,8 @@ namespace { // - FT_Deflection2D = 22 // v 9.3.0: FT_Undefined == 50, new items: // - FT_Length3D = 22 + // v 9.12.0: FT_Undefined == 51, new items: + // - FT_ScaledJacobian = 8 // // It's necessary to continue recording this history and to fill // undef2newItems (see below) accordingly. @@ -325,6 +327,7 @@ namespace { undef2newItems[ 48 ].push_back( 22 ); undef2newItems[ 49 ].push_back( 22 ); undef2newItems[ 50 ].push_back( 22 ); + undef2newItems[ 51 ].push_back( 8 ); ASSERT( undef2newItems.rbegin()->first == SMESH::FT_Undefined ); } diff --git a/src/SMESH_I/SMESH_Filter_i.cxx b/src/SMESH_I/SMESH_Filter_i.cxx index 2b2b9b7a2..cb9a44e4a 100644 --- a/src/SMESH_I/SMESH_Filter_i.cxx +++ b/src/SMESH_I/SMESH_Filter_i.cxx @@ -460,6 +460,21 @@ namespace SMESH { return SMESH::FT_Volume3D; } + /* + Class : ScaledJacobian_i + Description : Functor for calculating volume of 3D element + */ + ScaledJacobian_i::ScaledJacobian_i() + { + myNumericalFunctorPtr.reset( new Controls::ScaledJacobian() ); + myFunctorPtr = myNumericalFunctorPtr; + } + + FunctorType ScaledJacobian_i::GetFunctorType() + { + return SMESH::FT_ScaledJacobian; + } + /* Class : MaxElementLength2D_i Description : Functor for calculating maximum length of 2D element @@ -2126,6 +2141,13 @@ namespace SMESH { return anObj._retn(); } + ScaledJacobian_ptr FilterManager_i::CreateScaledJacobian() + { + SMESH::ScaledJacobian_i* aServant = new SMESH::ScaledJacobian_i(); + SMESH::ScaledJacobian_var anObj = aServant->_this(); + TPythonDump()<CreateNodeConnectivityNumber(); break; + case SMESH::FT_ScaledJacobian: + aFunctor = aFilterMgr->CreateScaledJacobian(); + break; // Predicates @@ -3512,6 +3537,7 @@ namespace SMESH { case FT_Skew : return "Skew"; case FT_Area : return "Area"; case FT_Volume3D : return "Volume3D"; + case FT_ScaledJacobian : return "ScaledJacobian"; case FT_MaxElementLength2D : return "Max element length 2D"; case FT_MaxElementLength3D : return "Max element length 3D"; case FT_BelongToMeshGroup : return "Belong to Mesh Group"; @@ -3568,6 +3594,7 @@ namespace SMESH { else if ( theStr.equals( "Skew" ) ) return FT_Skew; else if ( theStr.equals( "Area" ) ) return FT_Area; else if ( theStr.equals( "Volume3D" ) ) return FT_Volume3D; + else if ( theStr.equals( "ScaledJacobian" ) ) return FT_ScaledJacobian; else if ( theStr.equals( "Max element length 2D" ) ) return FT_MaxElementLength2D; else if ( theStr.equals( "Max element length 3D" ) ) return FT_MaxElementLength3D; else if ( theStr.equals( "Belong to Mesh Group" ) ) return FT_BelongToMeshGroup; @@ -4141,6 +4168,7 @@ namespace SMESH { "FT_Skew", "FT_Area", "FT_Volume3D", + "FT_ScaledJacobian", "FT_MaxElementLength2D", "FT_MaxElementLength3D", "FT_FreeBorders", diff --git a/src/SMESH_I/SMESH_Filter_i.hxx b/src/SMESH_I/SMESH_Filter_i.hxx index 2e57548b4..e4bb48b8e 100644 --- a/src/SMESH_I/SMESH_Filter_i.hxx +++ b/src/SMESH_I/SMESH_Filter_i.hxx @@ -351,6 +351,18 @@ namespace SMESH NodeConnectivityNumber_i(); FunctorType GetFunctorType(); }; + + /* + Class : ScaledJacobian_i + Description : Functor returning the scaled jacobian + */ + class SMESH_I_EXPORT ScaledJacobian_i: public virtual POA_SMESH::ScaledJacobian, + public virtual NumericalFunctor_i + { + public: + ScaledJacobian_i(); + FunctorType GetFunctorType(); + }; /* @@ -1113,6 +1125,7 @@ namespace SMESH Skew_ptr CreateSkew(); Area_ptr CreateArea(); Volume3D_ptr CreateVolume3D(); + ScaledJacobian_ptr CreateScaledJacobian(); MaxElementLength2D_ptr CreateMaxElementLength2D(); MaxElementLength3D_ptr CreateMaxElementLength3D(); Length_ptr CreateLength(); diff --git a/src/SMESH_I/SMESH_PythonDump.cxx b/src/SMESH_I/SMESH_PythonDump.cxx index 385f4be1d..643a82155 100644 --- a/src/SMESH_I/SMESH_PythonDump.cxx +++ b/src/SMESH_I/SMESH_PythonDump.cxx @@ -414,6 +414,7 @@ namespace SMESH case FT_Skew: myStream<< "aSkew"; break; case FT_Area: myStream<< "aArea"; break; case FT_Volume3D: myStream<< "aVolume3D"; break; + case FT_ScaledJacobian: myStream<< "aScaledJacobian"; break; case FT_MaxElementLength2D: myStream<< "aMaxElementLength2D"; break; case FT_MaxElementLength3D: myStream<< "aMaxElementLength3D"; break; case FT_FreeBorders: myStream<< "aFreeBorders"; break; diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 91d358d7b..d31be247e 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -1233,6 +1233,8 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): functor = aFilterMgr.CreateNodeConnectivityNumber() elif theCriterion == FT_BallDiameter: functor = aFilterMgr.CreateBallDiameter() + elif theCriterion == FT_ScaledJacobian: + functor = aFilterMgr.CreateScaledJacobian() else: print("Error: given parameter is not numerical functor type.") aFilterMgr.UnRegister() @@ -7469,6 +7471,19 @@ class Mesh(metaclass = MeshMeta): return self.FunctorValue(SMESH.FT_Skew, elemId) + def GetScaledJacobian(self, elemId): + """ + Get the scaled jacobian of 3D element id + + Parameters: + elemId: mesh element ID + + Returns: + the scaled jacobian + """ + + return self.FunctorValue(SMESH.FT_ScaledJacobian, elemId) + def GetMinMax(self, funType, meshPart=None): """ Return minimal and maximal value of a given functor. diff --git a/test/SMESH_controls_scaled_jacobian.py b/test/SMESH_controls_scaled_jacobian.py new file mode 100644 index 000000000..b7388ec4a --- /dev/null +++ b/test/SMESH_controls_scaled_jacobian.py @@ -0,0 +1,144 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2016-2023 CEA/DEN, EDF R&D +# +# 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, 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 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# File : SMESH_controls_scaled_jacobian.py +# Author : Cesar Conopoima +# Module : SMESH +# +import salome +import math +salome.salome_init_without_session() + +import GEOM +import SMESH +from salome.geom import geomBuilder +from salome.smesh import smeshBuilder + +def assertWithDelta( refval, testvals, delta ): + return ( refval <= testvals+delta and refval >= testvals-delta ) + +geompy = geomBuilder.New() +smesh_builder = smeshBuilder.New() + +Box_1 = geompy.MakeBoxDXDYDZ(10, 10, 10) +geompy.addToStudy( Box_1, 'Box_1' ) + +smesh = smeshBuilder.New() + +Mesh_1 = smesh.Mesh(Box_1,'Mesh_1') +NETGEN_1D_2D_3D = Mesh_1.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D) +Done = Mesh_1.Compute() + +if not Done: + raise Exception("Error when computing NETGEN_1D2D3D Mesh for quality control test") + +#For tetra elements +perfect = 1.0 +externals = math.sqrt( 2.0 )/2.0 +notPerfectElements = smesh.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_LessThan, perfect - 1e-12 ) +perfectElements = smesh.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_EqualTo, perfect ) +externalElements = smesh.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_EqualTo, externals ) + +notPerfectIds = Mesh_1.GetIdsFromFilter(notPerfectElements) +perfectIds = Mesh_1.GetIdsFromFilter(perfectElements) +externalsIds = Mesh_1.GetIdsFromFilter(externalElements) + +assert( len(notPerfectIds) == 4 ) +assert( len(perfectIds) == 1 ) +assert( len(externalsIds) == 4 ) + +# Test GetScaledJacobian by elementId +for id in range(len(perfectIds)): + assert( assertWithDelta( perfect, Mesh_1.GetScaledJacobian( perfectIds[ id ] ), 1e-12) ) + +for id in range(len(externalsIds)): + assert( assertWithDelta( externals, Mesh_1.GetScaledJacobian( externalsIds[ id ] ), 1e-12) ) + +#For hexa elements +Mesh_2 = smesh.Mesh(Box_1,'Mesh_2') +Cartesian_3D = Mesh_2.BodyFitted() +Body_Fitting_Parameters_1 = Cartesian_3D.SetGrid([ [ '5.0' ], [ 0, 1 ]],[ [ '5.0' ], [ 0, 1 ]],[ [ '5.0' ], [ 0, 1 ]],4,0) +Done = Mesh_2.Compute() + +if not Done: + raise Exception("Error when computing BodyFitted Mesh for quality control test") + +notPerfectIds = Mesh_2.GetIdsFromFilter(notPerfectElements) +perfectIds = Mesh_2.GetIdsFromFilter(perfectElements) + +assert( len(notPerfectIds) == 0 ) +assert( len(perfectIds) == 8 ) + +# Test GetScaledJacobian by elementId +for id in range(len(perfectIds)): + assert( assertWithDelta( perfect, Mesh_2.GetScaledJacobian( perfectIds[ id ] ), 1e-12) ) + +#For hexa elements with poor quality +Mesh_3 = smesh.Mesh(Box_1,'Mesh_3') +Cartesian_3D = Mesh_3.BodyFitted() +Body_Fitting_Parameters_1 = Cartesian_3D.SetGrid([ [ '5.0' ], [ 0, 1 ]],[ [ '5.0' ], [ 0, 1 ]],[ [ '5.0' ], [ 0, 1 ]],4,0) +Body_Fitting_Parameters_1.SetAxesDirs( SMESH.DirStruct( SMESH.PointStruct ( 1, 0, 1 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 1, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 0, 1 )) ) +Done = Mesh_3.Compute() + +if not Done: + raise Exception("Error when computing BodyFitted Distorted Mesh for quality control test") + +#Polyhedrons return zero scaled jacobian because of lack for a decomposition into simpler forms +Polys = 0.0 +#Hexahedrons that are distorted by an angle of 45 +# Scaled Jacobian which is a measure of elements distortion +# will return cos(45) = math.sqrt( 2.0 )/2.0 +distorted = math.sqrt( 2.0 )/2.0 +polysElements = smesh.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_EqualTo, Polys ) +distortedElements = smesh.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_EqualTo, distorted ) + +polysIds = Mesh_3.GetIdsFromFilter(polysElements) +distortedIds = Mesh_3.GetIdsFromFilter(distortedElements) + +assert( len(polysIds) == 4 ) +assert( len(distortedIds) == 8 ) + +# Test GetScaledJacobian by elementId +for id in range(len(distortedIds)): + assert( assertWithDelta( distorted, Mesh_3.GetScaledJacobian( distortedIds[ id ] ), 1e-12 ) ) + +#Test the pentahedron +Mesh_4 = smesh.Mesh(Box_1,'Mesh_4') +Cartesian_3D = Mesh_4.BodyFitted() +Body_Fitting_Parameters_1 = Cartesian_3D.SetGrid([ [ '4' ], [ 0, 1 ]],[ [ '4' ], [ 0, 1 ]],[ [ '4' ], [ 0, 1 ]],4,0) +Body_Fitting_Parameters_1.SetAxesDirs( SMESH.DirStruct( SMESH.PointStruct ( 1, 0, 1 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 1, 0 )), SMESH.DirStruct( SMESH.PointStruct ( 0, 0, 1 )) ) +Body_Fitting_Parameters_1.SetSizeThreshold( 4 ) +Body_Fitting_Parameters_1.SetToAddEdges( 0 ) +Body_Fitting_Parameters_1.SetGridSpacing( [ '2' ], [ 0, 1 ], 0 ) +Body_Fitting_Parameters_1.SetGridSpacing( [ '2' ], [ 0, 1 ], 1 ) +Body_Fitting_Parameters_1.SetGridSpacing( [ '2' ], [ 0, 1 ], 2 ) +Done = Mesh_4.Compute() + +if not Done: + raise Exception("Error when computing BodyFitted Distorted Mesh for quality control test") + +pentahedrons = 0.6 +pentasAndPolys = smesh.GetFilter(SMESH.VOLUME, SMESH.FT_ScaledJacobian, SMESH.FT_LessThan, pentahedrons ) +#Distorted hexas + +polysIds = Mesh_4.GetIdsFromFilter(polysElements) +pentasAndPolysIds = Mesh_4.GetIdsFromFilter(pentasAndPolys) + +assert( len(pentasAndPolysIds) - len(polysIds) == 10 ) diff --git a/test/tests.set b/test/tests.set index 92bb1df87..a983ddfe7 100644 --- a/test/tests.set +++ b/test/tests.set @@ -44,6 +44,7 @@ SET(BAD_TESTS SMESH_box3_tetra.py SMESH_box_tetra.py SMESH_controls.py + SMESH_controls_scaled_jacobian.py SMESH_fixation_netgen.py SMESH_fixation_tetra.py SMESH_flight_skin.py -- 2.30.2