Compare commits

..

No commits in common. "master" and "V9_14_0b1" have entirely different histories.

17 changed files with 61 additions and 521 deletions

View File

@ -41,18 +41,6 @@ ENDIF()
SALOME_SETUP_VERSION(9.13.0) SALOME_SETUP_VERSION(9.13.0)
MESSAGE(STATUS "Building ${PROJECT_NAME_UC} ${${PROJECT_NAME_UC}_VERSION} from \"${${PROJECT_NAME_UC}_GIT_SHA1}\"") MESSAGE(STATUS "Building ${PROJECT_NAME_UC} ${${PROJECT_NAME_UC}_VERSION} from \"${${PROJECT_NAME_UC}_GIT_SHA1}\"")
# Find SalomeBootstrap
# ===========
SET(SALOMEBOOTSTRAP_ROOT_DIR $ENV{SALOMEBOOTSTRAP_ROOT_DIR} CACHE PATH "Path to the Salome Bootstrap")
IF(EXISTS ${SALOMEBOOTSTRAP_ROOT_DIR})
FIND_PACKAGE(SalomeBootstrap REQUIRED)
ADD_DEFINITIONS(${SALOMEBOOTSTRAP_DEFINITIONS})
INCLUDE_DIRECTORIES(${SALOMEBOOTSTRAP_INCLUDE_DIRS})
ELSE(EXISTS ${SALOMEBOOTSTRAP_ROOT_DIR})
MESSAGE(FATAL_ERROR "We absolutely need a Salome Bootstrap, please define SALOMEBOOTSTRAP_ROOT_DIR")
ENDIF(EXISTS ${SALOMEBOOTSTRAP_ROOT_DIR})
# Find KERNEL # Find KERNEL
# =========== # ===========
SET(KERNEL_ROOT_DIR $ENV{KERNEL_ROOT_DIR} CACHE PATH "Path to the Salome KERNEL") SET(KERNEL_ROOT_DIR $ENV{KERNEL_ROOT_DIR} CACHE PATH "Path to the Salome KERNEL")

View File

@ -1,5 +1,4 @@
.. _a1d_meshing_hypo_page: .. _a1d_meshing_hypo_page:
.. |larr| unicode:: U+02190 .. LEFTWARDS ARROW
********************* *********************
1D Meshing Hypotheses 1D Meshing Hypotheses
@ -58,7 +57,7 @@ Adaptive hypothesis
Arithmetic Progression hypothesis Arithmetic Progression hypothesis
################################# #################################
**Arithmetic Progression** hypothesis allows to split edges into segments with a length that changes in arithmetic progression (L\ :sub:`k`\ |larr| L\ :sub:`k-1`\ + d) beginning from a given starting length and up to a given end length. **Arithmetic Progression** hypothesis allows to split edges into segments with a length that changes in arithmetic progression (Lk = Lk-1 + d) beginning from a given starting length and up to a given end length.
The splitting direction is defined by the orientation of the underlying geometrical edge. **Reverse Edges** list box allows specifying the edges, for which the splitting should be made in the direction opposite to their orientation. This list box is usable only if a geometry object is selected for meshing. In this case it is possible to select edges to be reversed either directly picking them in the 3D viewer or by selecting the edges or groups of edges in the Object Browser. Use The splitting direction is defined by the orientation of the underlying geometrical edge. **Reverse Edges** list box allows specifying the edges, for which the splitting should be made in the direction opposite to their orientation. This list box is usable only if a geometry object is selected for meshing. In this case it is possible to select edges to be reversed either directly picking them in the 3D viewer or by selecting the edges or groups of edges in the Object Browser. Use
**Add** button to add the selected edges to the list. **Add** button to add the selected edges to the list.
@ -83,7 +82,7 @@ The splitting direction is defined by the orientation of the underlying geometri
Geometric Progression hypothesis Geometric Progression hypothesis
################################ ################################
**Geometric Progression** hypothesis allows splitting edges into segments with a length that changes in geometric progression (L\ :sub:`k`\ |larr| L\ :sub:`k-1`\ * d) starting from a given **Start Length** and with a given **Common Ratio**. **Geometric Progression** hypothesis allows splitting edges into segments with a length that changes in geometric progression (Lk = Lk-1 * d) starting from a given **Start Length** and with a given **Common Ratio**.
The splitting direction is defined by the orientation of the underlying geometrical edge. The splitting direction is defined by the orientation of the underlying geometrical edge.
**Reverse Edges** list box allows specifying the edges, for which the splitting should be made in the direction opposite to their orientation. This list box is usable only if a geometry object is selected for meshing. In this case it is possible to select edges to be reversed either directly picking them in the 3D viewer or by selecting the edges or groups of edges in the Object Browser. Use **Add** button to add the selected edges to the list. **Reverse Edges** list box allows specifying the edges, for which the splitting should be made in the direction opposite to their orientation. This list box is usable only if a geometry object is selected for meshing. In this case it is possible to select edges to be reversed either directly picking them in the 3D viewer or by selecting the edges or groups of edges in the Object Browser. Use **Add** button to add the selected edges to the list.
@ -178,7 +177,7 @@ You can set the type of node distribution for this hypothesis in the **Hypothesi
**Scale Distribution** - length of segments gradually changes depending on the **Scale Factor**, which is a ratio of the first segment length to the last segment length. **Scale Distribution** - length of segments gradually changes depending on the **Scale Factor**, which is a ratio of the first segment length to the last segment length.
Length of segments changes in geometric progression with the common ratio (A) depending on the **Scale Factor** (S) and **Number of Segments** (N) as follows: A = S\ :sup:`(1/(N-1))`\ . For an edge of length L, length of the first segment is L * (1 - A)/(1 - A\ :sup:`N`\ ) Length of segments changes in geometric progression with the common ratio (A) depending on the **Scale Factor** (S) and **Number of Segments** (N) as follows: A = S**(1/(N-1)). For an edge of length L, length of the first segment is L * (1 - A)/(1 - A**N)
.. image:: ../images/a-nbsegments2.png .. image:: ../images/a-nbsegments2.png
:align: center :align: center

View File

@ -1131,7 +1131,6 @@ double AspectRatio3D::GetValue( const TSequenceOfXYZ& P )
if (nbNodes==10) nbNodes=4; // quadratic tetrahedron if (nbNodes==10) nbNodes=4; // quadratic tetrahedron
else if(nbNodes==13) nbNodes=5; // quadratic pyramid else if(nbNodes==13) nbNodes=5; // quadratic pyramid
else if(nbNodes==15) nbNodes=6; // quadratic pentahedron else if(nbNodes==15) nbNodes=6; // quadratic pentahedron
else if(nbNodes==18) nbNodes=6; // bi-quadratic pentahedron
else if(nbNodes==20) nbNodes=8; // quadratic hexahedron else if(nbNodes==20) nbNodes=8; // quadratic hexahedron
else if(nbNodes==27) nbNodes=8; // tri-quadratic hexahedron else if(nbNodes==27) nbNodes=8; // tri-quadratic hexahedron
else return aQuality; else return aQuality;

View File

@ -265,26 +265,26 @@ static int QuadPyram_RE [5][9] = { // REVERSED -> FORWARD (EXTERNAL)
{ 3, 8, 0, 9, 4, 12,3, 4, 4 }}; { 3, 8, 0, 9, 4, 12,3, 4, 4 }};
static int QuadPyram_nbN [] = { 8, 6, 6, 6, 6 }; static int QuadPyram_nbN [] = { 8, 6, 6, 6, 6 };
/* /*
// + N4 + // + N4
// /|\ /|\ // /|\
// 9/ | \10 + | + // 9/ | \10
// / | \ / | \ // / | \
// / | \ / | \ // / | \
// N3 +----+----+ N5 +----+----+ // N3 +----+----+ N5
// | |11 | | | | // | |11 |
// | | | | | | Central nodes // | | |
// | +13 | QUADRATIC | 16 + | of bi-quadratic // | +13 | QUADRATIC
// | | | PENTAHEDRON | + | + | PENTAHEDRON // | | | PENTAHEDRON
// 12+ | +14 + | 17 + // 12+ | +14
// | | | | 18| | // | | |
// | | | | | | // | | |
// | + N1 | | + | // | + N1 |
// | / \ | | / \ | // | / \ |
// | 6/ \7 | | + + | // | 6/ \7 |
// | / \ | | / \ | // | / \ |
// |/ \| |/ \| // |/ \|
// N0 +---------+ N2 +---------+ // N0 +---------+ N2
// 8 // 8
*/ */
static int QuadPenta_F [5][9] = { // FORWARD static int QuadPenta_F [5][9] = { // FORWARD
@ -301,20 +301,6 @@ static int QuadPenta_RE [5][9] = { // REVERSED -> EXTERNAL
{ 0, 12,3, 11,5, 14,2, 8, 0 }}; { 0, 12,3, 11,5, 14,2, 8, 0 }};
static int QuadPenta_nbN [] = { 6, 6, 8, 8, 8 }; static int QuadPenta_nbN [] = { 6, 6, 8, 8, 8 };
static int BiQuadPenta_F[5][9] = { // FORWARD
{ 0, 6, 1, 7, 2, 8, 0, 0, 0 },
{ 3, 11,5, 10,4, 9, 3, 3, 3 },
{ 0, 12,3, 9, 4, 13,1, 6, 16}, //!
{ 1, 13,4, 10,5, 14,2, 7, 17}, //!
{ 0, 8, 2, 14,5, 11,3, 12,18} }; //!
static int BiQuadPenta_RE[5][9] = { // REVERSED -> EXTERNAL
{ 0, 8, 2, 7, 1, 6, 0, 0, 0 },
{ 3, 9, 4, 10,5, 11,3, 3, 3 },
{ 0, 6, 1, 13,4, 9, 3, 12,17}, //!
{ 1, 7, 2, 14,5, 10,4, 13,16}, //!
{ 0, 12,3, 11,5, 14,2, 8, 18} }; //!
static int BiQuadPenta_nbN[] = { 6, 6, 9, 9, 9 };
/* /*
// 13 // 13
// N5+-----+-----+N6 +-----+-----+ // N5+-----+-----+N6 +-----+-----+
@ -648,14 +634,6 @@ void SMDS_VolumeTool::Inverse ()
SWAP_NODES( myVolumeNodes, 9, 11 ); SWAP_NODES( myVolumeNodes, 9, 11 );
SWAP_NODES( myVolumeNodes, 13, 14 ); SWAP_NODES( myVolumeNodes, 13, 14 );
break; break;
case 18:
SWAP_NODES(myVolumeNodes, 1, 2);
SWAP_NODES(myVolumeNodes, 4, 5);
SWAP_NODES(myVolumeNodes, 6, 8);
SWAP_NODES(myVolumeNodes, 9, 11);
SWAP_NODES(myVolumeNodes, 13, 14);
SWAP_NODES(myVolumeNodes, 16, 17);
break;
case 20: case 20:
SWAP_NODES( myVolumeNodes, 1, 3 ); SWAP_NODES( myVolumeNodes, 1, 3 );
SWAP_NODES( myVolumeNodes, 5, 7 ); SWAP_NODES( myVolumeNodes, 5, 7 );
@ -699,7 +677,6 @@ SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetVolumeType() const
case 10: return QUAD_TETRA; case 10: return QUAD_TETRA;
case 13: return QUAD_PYRAM; case 13: return QUAD_PYRAM;
case 15: return QUAD_PENTA; case 15: return QUAD_PENTA;
case 18: return QUAD_PENTA;
case 20: return QUAD_HEXA; case 20: return QUAD_HEXA;
case 27: return QUAD_HEXA; case 27: return QUAD_HEXA;
default: break; default: break;
@ -885,8 +862,6 @@ double SMDS_VolumeTool::GetSize() const
myVolumeNodes[ vtab[i][2] ], myVolumeNodes[ vtab[i][2] ],
myVolumeNodes[ vtab[i][3] ]); myVolumeNodes[ vtab[i][3] ]);
} }
if (!myVolForward && V < 0)
V *= -1;
} }
return V; return V;
} }
@ -1730,16 +1705,6 @@ int SMDS_VolumeTool::GetCenterNodeIndex( int faceIndex ) const
return faceIndex + 19; return faceIndex + 19;
} }
} }
else if (myAllFacesNbNodes && myVolumeNodes.size() == 18) // element with 18 nodes
{
switch (faceIndex) {
case 2: return 15;
case 3: return 16;
case 4: return 17;
default:
return -2;
}
}
return -1; return -1;
} }
@ -1762,7 +1727,6 @@ int SMDS_VolumeTool::GetOppFaceIndex( int faceIndex ) const
switch ( myVolumeNodes.size() ) { switch ( myVolumeNodes.size() ) {
case 6: case 6:
case 15: case 15:
case 18:
if ( faceIndex == 0 || faceIndex == 1 ) if ( faceIndex == 0 || faceIndex == 1 )
ind = 1 - faceIndex; ind = 1 - faceIndex;
break; break;
@ -2505,7 +2469,6 @@ bool SMDS_VolumeTool::setFace( int faceIndex ) const
myMaxFaceNbNodes = sizeof(QuadPyram_F[0])/sizeof(QuadPyram_F[0][0]); myMaxFaceNbNodes = sizeof(QuadPyram_F[0])/sizeof(QuadPyram_F[0][0]);
break; break;
case 15: case 15:
case 18:
myAllFacesNodeIndices_F = &QuadPenta_F [0][0]; myAllFacesNodeIndices_F = &QuadPenta_F [0][0];
//myAllFacesNodeIndices_FE = &QuadPenta_FE[0][0]; //myAllFacesNodeIndices_FE = &QuadPenta_FE[0][0];
myAllFacesNodeIndices_RE = &QuadPenta_RE[0][0]; myAllFacesNodeIndices_RE = &QuadPenta_RE[0][0];
@ -2572,8 +2535,7 @@ SMDS_VolumeTool::VolumeType SMDS_VolumeTool::GetType(int nbNodes)
case 8: return HEXA; case 8: return HEXA;
case 10: return QUAD_TETRA; case 10: return QUAD_TETRA;
case 13: return QUAD_PYRAM; case 13: return QUAD_PYRAM;
case 15: case 15: return QUAD_PENTA;
case 18: return QUAD_PENTA;
case 20: case 20:
case 27: return QUAD_HEXA; case 27: return QUAD_HEXA;
case 12: return HEX_PRISM; case 12: return HEX_PRISM;

View File

@ -86,8 +86,6 @@
namespace fs=boost::filesystem; namespace fs=boost::filesystem;
#endif #endif
#include <unordered_set>
// maximum stored group name length in MED file // maximum stored group name length in MED file
#define MAX_MED_GROUP_NAME_LENGTH 80 #define MAX_MED_GROUP_NAME_LENGTH 80
@ -715,8 +713,6 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
} }
} }
} }
ret = CheckHypothesesOnSubMeshes(subMesh, anHyp, event);
} }
HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
GetMeshDS()->Modified(); GetMeshDS()->Modified();
@ -1006,78 +1002,6 @@ SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const
return anHyp; 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,11 +175,6 @@ class SMESH_EXPORT SMESH_Mesh
SMESH_Hypothesis * GetHypothesis(const int aHypID) const; 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(); const std::list<SMESHDS_Command*> & GetLog();
void ClearLog(); void ClearLog();

View File

@ -9483,8 +9483,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT
case SMDSEntity_TriQuad_Hexa: case SMDSEntity_TriQuad_Hexa:
NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d); nodes[4], nodes[5], nodes[6], nodes[7], id, theForce3d);
for (size_t i = 8; i < nodes.size(); ++i) // rm central nodes from each edge for ( size_t i = 20; i < nodes.size(); ++i ) // rm central nodes
//for (size_t i = 20; i < nodes.size(); ++i) // rm central nodes from each edge
if ( nodes[i]->NbInverseElements() == 0 ) if ( nodes[i]->NbInverseElements() == 0 )
GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true ); GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true );
break; break;
@ -9497,9 +9496,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT
case SMDSEntity_BiQuad_Penta: case SMDSEntity_BiQuad_Penta:
NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
nodes[3], nodes[4], nodes[5], id, theForce3d); nodes[3], nodes[4], nodes[5], id, theForce3d);
for ( size_t i = 15; i < nodes.size(); ++i ) // rm central nodes
for (size_t i = 6; i < nodes.size(); ++i) // rm central nodes
//for ( size_t i = 15; i < nodes.size(); ++i ) // rm central nodes
if ( nodes[i]->NbInverseElements() == 0 ) if ( nodes[i]->NbInverseElements() == 0 )
GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true ); GetMeshDS()->RemoveFreeNode( nodes[i], /*sm=*/0, /*fromGroups=*/true );
break; break;
@ -13040,58 +13037,15 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
if (iQuad) if (iQuad)
for ( inode = 1; inode < nbFaceNodes; inode += 2) for ( inode = 1; inode < nbFaceNodes; inode += 2)
nodes.push_back( nn[inode] ); // add medium nodes nodes.push_back( nn[inode] ); // add medium nodes
// for triangle face for Penta18 (BiQuadratic pentahedron) return -2
// because we haven't center node on triangle side, but it's need for create biquadratic face
int iCenter = vTool.GetCenterNodeIndex(iface); // for HEX27 int iCenter = vTool.GetCenterNodeIndex(iface); // for HEX27
if ( iCenter > 0 )
nodes.push_back( vTool.GetNodes()[ iCenter ] );
// for triangle faces for Penta18 (BiQuadratic pentahedron) firstly check, exist face or not if (const SMDS_MeshElement * f = aMesh->FindElement( nodes,
// if not - create node in middle face SMDSAbs_Face, /*noMedium=*/false ))
if (iCenter == -2) presentBndElems.push_back( f );
{
SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
bool isFound = false;
while (itF->more())
{
const SMDS_MeshElement* e = itF->next();
int nbNodesToCheck = e->NbNodes();
if (nbNodesToCheck == (int)nodes.size() + 1)
{
for (size_t i = 1; e && i < nodes.size() - 1; ++i)
{
int nodeIndex = e->GetNodeIndex(nodes[i]);
if (nodeIndex < 0 || nodeIndex >= nbNodesToCheck)
e = 0;
}
if (e)
{
presentBndElems.push_back(e);
isFound = true;
}
}
}
if (!isFound)
{
SMESH_MesherHelper aHelper(*myMesh);
double bc[3];
vTool.GetFaceBaryCenter(iface, bc[0], bc[1], bc[2]);
auto aNodeC = aHelper.AddNode(bc[0], bc[1], bc[2]);
nodes.push_back(aNodeC);
missingBndElems.push_back(nodes);
}
}
else else
{ missingBndElems.push_back( nodes );
if (iCenter > 0)
nodes.push_back(vTool.GetNodes()[iCenter]);
if (const SMDS_MeshElement* f = aMesh->FindElement(nodes,
SMDSAbs_Face, /*noMedium=*/false))
presentBndElems.push_back(f);
else
missingBndElems.push_back(nodes);
}
if ( targetMesh != myMesh ) if ( targetMesh != myMesh )
{ {

View File

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

View File

@ -23,7 +23,6 @@ INCLUDE_DIRECTORIES(
${KERNEL_INCLUDE_DIRS} ${KERNEL_INCLUDE_DIRS}
${OpenCASCADE_INCLUDE_DIR} ${OpenCASCADE_INCLUDE_DIR}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${SALOMEBOOTSTRAP_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/src/SMDS ${PROJECT_SOURCE_DIR}/src/SMDS
) )
@ -39,7 +38,6 @@ SET(_link_LIBRARIES
${OpenCASCADE_FoundationClasses_LIBRARIES} ${OpenCASCADE_FoundationClasses_LIBRARIES}
${OpenCASCADE_ModelingData_LIBRARIES} ${OpenCASCADE_ModelingData_LIBRARIES}
${Boost_LIBRARIES} ${Boost_LIBRARIES}
SALOMEException
SMDS SMDS
) )

View File

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

View File

@ -230,7 +230,7 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
} }
// remove free nodes // remove free nodes
//if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( helper.GetSubShapeID() )) if ( /*SMESHDS_SubMesh * smDS = */meshDS->MeshElements( helper.GetSubShapeID() ))
{ {
std::vector< const SMDS_MeshNode* > nodesToRemove; std::vector< const SMDS_MeshNode* > nodesToRemove;
// get intersection nodes // get intersection nodes

View File

@ -579,14 +579,6 @@ namespace {
case HAS_PROPAG_HYP: { // propag hyp on this submesh case HAS_PROPAG_HYP: { // propag hyp on this submesh
// -------------------------------------------------------- // --------------------------------------------------------
switch ( event ) { 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_HYP:
case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp
if ( isPropagHyp && !getProagationHyp( subMesh )) if ( isPropagHyp && !getProagationHyp( subMesh ))

View File

@ -492,105 +492,6 @@ static void compensateError(double a1, double an,
} }
} }
//================================================================================
/*!
* \brief adjust internal node parameters so that the last segment length == an,
* and by distributing the error for the total length of curve segments
* in relation to the target length computed from the current parameters
* \param a1 - the first segment length
* \param an - the last segment length
* \param U1 - the first edge parameter
* \param Un - the last edge parameter
* \param length - the edge length
* \param C3d - the edge curve
* \param theParams - internal node parameters to adjust
*/
//================================================================================
static void distributeError(double a1, double an,
double U1, double Un,
double length,
Adaptor3d_Curve& C3d,
list<double> & theParams)
{
// Compute the error of the total length based in the current curve parameters
double tol = Min( Precision::Confusion(), 0.01 * Min(a1, an) );
double totalLength = 0.0;
double prevParam = U1;
list<double> segLengths;
list<double>::iterator itU = theParams.begin();
for ( ; itU != theParams.end(); ++itU )
{
// Compute the curve length between two adjacent parameters and sum them up
double curLength = GCPnts_AbscissaPoint::Length(C3d, prevParam, *itU, tol);
segLengths.push_back(curLength);
totalLength += curLength;
prevParam = *itU;
}
// Calculate the error between the total length of all segments based on given parameters
// and the target length of the edge itself
double error = totalLength - length;
// Compute the sum of all internal segments (= total computed length minus the length of
// the start and end segments)
double midLength = totalLength - (a1 + an);
// We only need to distribute the error, if the current parametrization is not correct,
// and if there are multiple internal segments
smIdType nPar = theParams.size();
if ( a1 + an <= length && nPar > 1 && fabs(error) > tol )
{
// Update the length of each internal segment (start and end length are given and not changed)
double newTotalLength = 0.0;
double newLength;
double relError = error / midLength;
list<double> newSegLengths;
list<double>::iterator itL = segLengths.begin();
for ( ; itL != segLengths.end(); ++itL )
{
// Do not update, but copy the first and the last segment lengths
newLength = *itL;
if (itL != segLengths.begin() && itL != --segLengths.end())
{
newLength -= newLength * relError;
}
newSegLengths.push_back(newLength);
newTotalLength += newLength;
}
bool reverse = ( U1 > Un );
// Update the parameters of the curve based on the new lengths
double curveLength, tol2, U;
double prevU = U1;
itU = theParams.begin();
itL = newSegLengths.begin();
for ( ; itU != theParams.end(); ++itU, ++itL )
{
curveLength = (reverse ? -(*itL) : *itL);
tol2 = Min( Precision::Confusion(), fabs(curveLength) / 100. );
GCPnts_AbscissaPoint Discret( tol2, C3d, curveLength, prevU );
if ( !Discret.IsDone() )
{
return;
}
U = Discret.Parameter();
double sign = reverse ? -1 : 1;
if ( sign*U1 < sign*U && sign*U < sign*Un )
{
*itU = U;
}
else
{
*itU = (sign*U >= sign*Un ? Un : U1);
break;
}
prevU = U;
}
}
}
//================================================================================ //================================================================================
/*! /*!
* \brief Class used to clean mesh on edges when 0D hyp modified. * \brief Class used to clean mesh on edges when 0D hyp modified.
@ -1141,9 +1042,8 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh,
return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<< return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
"for an edge of length "<<theLength); "for an edge of length "<<theLength);
// Compute first the number of segments and then the arithmetic increment based on that number double q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
int n = static_cast<int>(2 * theLength / ( a1 + an ) + 0.5); int n = int(fabs(q) > numeric_limits<double>::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 ));
double q = (n > 1 ? ( an - a1 ) / (n - 1) : 0.0);
double U1 = theReverse ? l : f; double U1 = theReverse ? l : f;
double Un = theReverse ? f : l; double Un = theReverse ? f : l;
@ -1154,23 +1054,19 @@ bool StdMeshers_Regular_1D::computeInternalParameters(SMESH_Mesh & theMesh,
eltSize = -eltSize; eltSize = -eltSize;
q = -q; q = -q;
} }
for (int i=0; i<n; i++) { while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
// computes a point on a curve <theC3d> at the distance <eltSize> // computes a point on a curve <theC3d> at the distance <eltSize>
// from the point of parameter <param>. // from the point of parameter <param>.
GCPnts_AbscissaPoint Discret( tol, theC3d, eltSize, param ); GCPnts_AbscissaPoint Discret( tol, theC3d, eltSize, param );
if ( !Discret.IsDone() ) break; if ( !Discret.IsDone() ) break;
param = Discret.Parameter(); param = Discret.Parameter();
theParams.push_back( param ); if ( param > f && param < l )
theParams.push_back( param );
else
break;
eltSize += q; eltSize += q;
} }
compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
distributeError( a1, an, U1, Un, theLength, theC3d, theParams );
// Do not include the parameter for the start or end of an edge in the list of parameters
// NOTE: it is required to correctly distribute the error
if (fabs(theParams.front() - U1) < tol) theParams.pop_front();
if (fabs(theParams.back() - Un) < tol) theParams.pop_back();
if ( theReverse ) theParams.reverse(); // NPAL18025 if ( theReverse ) theParams.reverse(); // NPAL18025
return true; return true;

View File

@ -1867,30 +1867,26 @@ bool _ViscousBuilder2D::shrink()
Geom2dAdaptor_Curve edgeCurve( pcurve, Min( uf, ul ), Max( uf, ul )); Geom2dAdaptor_Curve edgeCurve( pcurve, Min( uf, ul ), Max( uf, ul ));
Geom2dAdaptor_Curve seg2Curve( seg2Line ); Geom2dAdaptor_Curve seg2Curve( seg2Line );
Geom2dInt_GInter curveInt( edgeCurve, seg2Curve, 1e-7, 1e-7 ); Geom2dInt_GInter curveInt( edgeCurve, seg2Curve, 1e-7, 1e-7 );
// In the older version length2D was set to this value only inside the !convex if block
// But it seems that length2D can be set here anyway, because if not set valid value of length2D here,
// it will be calculated later using length1D, and it can be not valid in cases if length1D is too large or too small.
length2D = L2->_lEdges[iFSeg2]._length2D;
/* convex VERTEX
* L seg2
* | o---o---
* | / |
* |/ | L2
* x------x--- */
/* concave VERTEX
* o-----o---
* \ |
* \ | L2
* x--x---
* /
* L / */
isConvex = ( curveInt.IsDone() && !curveInt.IsEmpty() ); isConvex = ( curveInt.IsDone() && !curveInt.IsEmpty() );
if ( isConvex ) if ( isConvex ) {
{ /* convex VERTEX */
length1D = Abs( u - curveInt.Point( 1 ).ParamOnFirst() ); length1D = Abs( u - curveInt.Point( 1 ).ParamOnFirst() );
length2D = Max(length2D, length1D / len1dTo2dRatio); double maxDist2d = 2 * L2->_lEdges[ iLSeg2 ]._length2D;
isConvex = ( length1D < maxDist2d * len1dTo2dRatio );
/* |L seg2
* | o---o---
* | / |
* |/ | L2
* x------x--- */
}
if ( !isConvex ) { /* concave VERTEX */ /* o-----o---
* \ |
* \ | L2
* x--x---
* /
* L / */
length2D = L2->_lEdges[ iFSeg2 ]._length2D;
//if ( L2->_advancable ) continue;
} }
} }
else // L2 is advancable but in the face adjacent by L else // L2 is advancable but in the face adjacent by L

View File

@ -1,81 +0,0 @@
# 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()

View File

@ -1,80 +0,0 @@
# 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,8 +109,6 @@ SET(GOOD_TESTS
ex31_dimGroup.py ex31_dimGroup.py
PAL_MESH_043_2D.py PAL_MESH_043_2D.py
SMESH_AdvancedEditor.py SMESH_AdvancedEditor.py
SMESH_algo_switch_box.py
SMESH_algo_switch_face.py
SMESH_blocks.py SMESH_blocks.py
SMESH_box.py SMESH_box.py
SMESH_BuildCompound.py SMESH_BuildCompound.py