[bos #43370] Swich Composite Side to Wire Discretization. Fixed when a propagation chain weren't rebuilt after changing an algorithm on father mesh. Added tests. Added a note about calling base class clear() for a child of SMDS_ElementHolder. Removed redundant output.

This commit is contained in:
Konstantin Leontev 2024-11-08 13:53:59 +00:00 committed by mbs
parent 63567f57a1
commit 9dd9f7684c
8 changed files with 254 additions and 2 deletions

View File

@ -86,6 +86,8 @@
namespace fs=boost::filesystem;
#endif
#include <unordered_set>
// maximum stored group name length in MED file
#define MAX_MED_GROUP_NAME_LENGTH 80
@ -713,6 +715,8 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
}
}
}
ret = CheckHypothesesOnSubMeshes(subMesh, anHyp, event);
}
HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
GetMeshDS()->Modified();
@ -1002,6 +1006,78 @@ SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const
return anHyp;
}
//================================================================================
/*!
* \brief Iterates hypotesis for all sub-meshes of the given sub-mesh and checks
algo state with the given event. The goal is to address hypothesis those are
not directly affected by changing of an algorithm of the given sub-shape.
It is essential to rebuild propagation chains of such hypotheses, otherwise the chains
are being cleared after editing of the algorithm and never rebuilt again.
* \param subMesh - the main sub-mesh to check sub-meshes of
* \param anHyp - the hypothesis changed on the given sub-mesh, we need to skip it from checking
* \param event - the given event
* \retval SMESH_Hypothesis::Hypothesis_Status - HYP_OK if no errors found, otherwise the most severe error
*/
//================================================================================
SMESH_Hypothesis::Hypothesis_Status SMESH_Mesh::CheckHypothesesOnSubMeshes(
SMESH_subMesh* subMesh,
const SMESH_Hypothesis* anHyp,
const SMESH_subMesh::algo_event event) const
{
SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::Hypothesis_Status::HYP_OK;
// Cache the processed hypotheses for performance reasons.
// Given hypothesis is already processed, so should be skipped.
std::unordered_set<const SMESH_Hypothesis*> processedHypotheses = { anHyp };
// Look through sub-meshes of the given sub-mesh
SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false, false);
while (smIt->more())
{
const SMESH_subMesh* sm = smIt->next();
const SMESH_Algo* algo = sm->GetAlgo();
if (!algo)
continue;
const SMESH_HypoFilter* hypoKind = algo->GetCompatibleHypoFilter(false);
if (!hypoKind)
continue;
std::list <const SMESHDS_Hypothesis*> usedHyps;
if (!GetHypotheses(sm, *hypoKind, usedHyps, true))
continue;
// Look through hypotheses used by algo
for (const auto* usedHyp : usedHyps)
{
SMESH_Hypothesis* hyp = GetHypothesis(usedHyp->GetID());
if (hyp == anHyp)
continue;
if (processedHypotheses.find(hyp) != processedHypotheses.end())
continue;
processedHypotheses.insert(hyp); // Cache the hypothesis pointer
// Hypoteses restricted by Propagation only because of failed tests.
// It's ok for now, because this method was created to fix propagation issue.
// It should be investigated more if we find similar issues with other hypotheses.
const char* hypName = hyp->GetName();
if (strcmp(hypName, "Propagation") != 0)
continue;
const SMESH_Hypothesis::Hypothesis_Status ret2 = subMesh->SubMeshesAlgoStateEngine(event, hyp, true);
if (ret2 > ret)
{
ret = ret2;
break;
}
}
}
return ret;
}
//=============================================================================
/*!
*

View File

@ -175,6 +175,11 @@ class SMESH_EXPORT SMESH_Mesh
SMESH_Hypothesis * GetHypothesis(const int aHypID) const;
SMESH_Hypothesis::Hypothesis_Status CheckHypothesesOnSubMeshes(
SMESH_subMesh* subMesh,
const SMESH_Hypothesis* anHyp,
const SMESH_subMesh::algo_event event) const;
const std::list<SMESHDS_Command*> & GetLog();
void ClearLog();

View File

@ -86,6 +86,8 @@ class SMESHDS_EXPORT SMESHDS_SubMesh : public SMDS_ElementHolder
virtual void tmpClear();
virtual void add( const SMDS_MeshElement* element );
virtual void compact() {}
// Commented out to avoid SMESH_netgen_runner_1D2D3D test failure
// virtual void clear() override { Clear(); }
private:

View File

@ -3483,7 +3483,6 @@ void SMESH_Mesh_i::onHypothesisModified(int theHypID, bool theUpdateIcons)
void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
{
MESSAGE("SMESH_Mesh_i::SetImpl");
_impl = impl;
if ( _impl )
_impl->SetCallUp( new TCallUp_i(this));
@ -3497,7 +3496,6 @@ void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
::SMESH_Mesh & SMESH_Mesh_i::GetImpl()
{
MESSAGE("SMESH_Mesh_i::GetImpl()");
return *_impl;
}

View File

@ -579,6 +579,14 @@ namespace {
case HAS_PROPAG_HYP: { // propag hyp on this submesh
// --------------------------------------------------------
switch ( event ) {
case SMESH_subMesh::ADD_FATHER_ALGO:
{
DBGMSG("HAS_PROPAG_HYP propagation to ADD_FATHER_ALGO " << subMesh->GetId());
// Rebuild propagation chain after an algo was added on father submesh
buildPropagationChain(subMesh);
break;
}
case SMESH_subMesh::REMOVE_HYP:
case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp
if ( isPropagHyp && !getProagationHyp( subMesh ))

81
test/SMESH_algo_switch_box.py Executable file
View File

@ -0,0 +1,81 @@
# Tests that switching of algorithms back and forth does not lead to errors
import salome
salome.salome_init()
from salome.geom import geomBuilder
import SMESH
from salome.smesh import smeshBuilder
# Create a box
geompy = geomBuilder.New()
O = geompy.MakeVertex(0, 0, 0)
OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
edge = geompy.CreateGroup(Box_1, geompy.ShapeType["EDGE"])
geompy.UnionIDs(edge, [26])
[edge] = geompy.GetExistingSubObjects(Box_1, False)
geompy.addToStudy( O, 'O' )
geompy.addToStudy( OX, 'OX' )
geompy.addToStudy( OY, 'OY' )
geompy.addToStudy( OZ, 'OZ' )
geompy.addToStudy( Box_1, 'Box_1' )
geompy.addToStudyInFather( Box_1, edge, 'edge' )
# Create a mesh from the box and a sub-mesh from an edge
smesh = smeshBuilder.New()
Mesh_1 = smesh.Mesh(Box_1,'Mesh_1')
Regular_1D = Mesh_1.Segment()
Number_of_Segments_1 = Regular_1D.NumberOfSegments(15)
Quadrangle_2D = Mesh_1.Quadrangle(algo=smeshBuilder.QUADRANGLE)
Hexa_3D = Mesh_1.Hexahedron(algo=smeshBuilder.Hexa)
edge_1 = Mesh_1.GroupOnGeom(edge,'edge',SMESH.EDGE)
Regular_1D_1 = Mesh_1.Segment(geom=edge)
Number_of_Segments_2 = Regular_1D_1.NumberOfSegments(2)
Propagation_of_1D_Hyp = Regular_1D_1.Propagation()
# Compute initial mesh
Mesh_1.Compute()
Mesh_1.CheckCompute()
Sub_mesh_1 = Regular_1D_1.GetSubMesh()
# Get the number of faces in the mesh
num_faces_before = Mesh_1.NbFaces()
print('Number of faces before switching: %d' % num_faces_before)
# Switch to composite segment algorithm and compute the mesh
status = Mesh_1.RemoveHypothesis(Regular_1D)
CompositeSegment_1D = Mesh_1.Segment(algo=smeshBuilder.COMPOSITE)
Mesh_1.AddHypothesis(CompositeSegment_1D)
isDone = Mesh_1.Compute()
Mesh_1.CheckCompute() # if propagation doesn't work it already fails here
# Switch back to regular segment algorithm and compute the mesh
status = Mesh_1.RemoveHypothesis(CompositeSegment_1D)
Mesh_1.AddHypothesis(Regular_1D)
Mesh_1.Compute()
Mesh_1.CheckCompute()
# Get the number of faces in the mesh
num_faces_after = Mesh_1.NbFaces()
print('Number of faces after switching: %d' % num_faces_after)
assert num_faces_before == num_faces_after, 'Number of faces before and after switching should be the same'
## Set names of Mesh objects
smesh.SetName(CompositeSegment_1D.GetAlgorithm(), 'CompositeSegment_1D')
smesh.SetName(Number_of_Segments_1, 'Number of Segments_1')
smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1')
smesh.SetName(Number_of_Segments_2, 'Number of Segments_2')
smesh.SetName(edge_1, 'edge')
smesh.SetName(Hexa_3D.GetAlgorithm(), 'Hexa_3D')
smesh.SetName(Sub_mesh_1, 'Sub-mesh_1')
smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D')
smesh.SetName(Propagation_of_1D_Hyp, 'Propagation of 1D Hyp. on Opposite Edges_1')
smesh.SetName(Quadrangle_2D.GetAlgorithm(), 'Quadrangle_2D')
if salome.sg.hasDesktop():
salome.sg.updateObjBrowser()

80
test/SMESH_algo_switch_face.py Executable file
View File

@ -0,0 +1,80 @@
# Tests that switching of algorithms back and forth does not lead to errors
import salome
salome.salome_init()
from salome.geom import geomBuilder
import SMESH
from salome.smesh import smeshBuilder
# Create a simple face
geompy = geomBuilder.New()
O = geompy.MakeVertex(0, 0, 0)
OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
Face_1 = geompy.MakeFaceHW(100, 100, 1)
edge = geompy.CreateGroup(Face_1, geompy.ShapeType['EDGE'])
geompy.UnionIDs(edge, [6])
[edge] = geompy.GetExistingSubObjects(Face_1, False)
geompy.addToStudy( O, 'O' )
geompy.addToStudy( OX, 'OX' )
geompy.addToStudy( OY, 'OY' )
geompy.addToStudy( OZ, 'OZ' )
geompy.addToStudy( Face_1, 'Face_1' )
geompy.addToStudyInFather( Face_1, edge, 'edge' )
# Create a mesh from the face and a sub-mesh from an edge
smesh = smeshBuilder.New()
Mesh_1 = smesh.Mesh(Face_1,'Mesh_1')
Regular_1D = Mesh_1.Segment()
Number_of_Segments_1 = Regular_1D.NumberOfSegments(3)
Quadrangle_2D = Mesh_1.Quadrangle(algo=smeshBuilder.QUADRANGLE)
edge_1 = Mesh_1.GroupOnGeom(edge,'edge',SMESH.EDGE)
Regular_1D_1 = Mesh_1.Segment(geom=edge)
Number_of_Segments_2 = Regular_1D_1.NumberOfSegments(2)
Propagation_of_1D_Hyp = Regular_1D_1.Propagation()
# Compute initial mesh
Mesh_1.Compute()
Mesh_1.CheckCompute()
Sub_mesh_1 = Regular_1D_1.GetSubMesh()
# Get the number of faces in the mesh
num_faces_before = Mesh_1.NbFaces()
print('Number of faces before switching: %d' % num_faces_before)
# Switch to composite segment algorithm and compute the mesh
status = Mesh_1.RemoveHypothesis(Regular_1D)
CompositeSegment_1D = smesh.CreateHypothesis('CompositeSegment_1D')
Mesh_1.AddHypothesis(CompositeSegment_1D)
Mesh_1.Compute()
Mesh_1.CheckCompute()
# Switch back to regular segment algorithm and compute the mesh
status = Mesh_1.RemoveHypothesis(CompositeSegment_1D)
Mesh_1.AddHypothesis(Regular_1D)
Mesh_1.Compute()
Mesh_1.CheckCompute()
# Get the number of faces in the mesh
num_faces_after = Mesh_1.NbFaces()
print('Number of faces after switching: %d' % num_faces_after)
assert num_faces_before == num_faces_after, 'Number of faces before and after switching should be the same'
## Set names of Mesh objects
smesh.SetName(CompositeSegment_1D, 'CompositeSegment_1D')
smesh.SetName(Number_of_Segments_1, 'Number of Segments_1')
smesh.SetName(Mesh_1.GetMesh(), 'Mesh_1')
smesh.SetName(Number_of_Segments_2, 'Number of Segments_2')
smesh.SetName(edge_1, 'edge')
smesh.SetName(Sub_mesh_1, 'Sub-mesh_1')
smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D')
smesh.SetName(Propagation_of_1D_Hyp, 'Propagation of 1D Hyp. on Opposite Edges_1')
smesh.SetName(Quadrangle_2D.GetAlgorithm(), 'Quadrangle_2D')
if salome.sg.hasDesktop():
salome.sg.updateObjBrowser()

View File

@ -109,6 +109,8 @@ SET(GOOD_TESTS
ex31_dimGroup.py
PAL_MESH_043_2D.py
SMESH_AdvancedEditor.py
SMESH_algo_switch_box.py
SMESH_algo_switch_face.py
SMESH_blocks.py
SMESH_box.py
SMESH_BuildCompound.py