mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2024-11-11 16:19:16 +05:00
bos #17015 [CEA 17008] Body fitting with Viscous Layers for CFD meshing
fix for inlet/outlet Fix for negative volumes due to merge increase tolerance for search of equal intersection points Remove old tol2 declaration
This commit is contained in:
parent
a53a9fc74d
commit
c9294ee688
@ -7,7 +7,9 @@ Body Fitting 3D meshing algorithm
|
||||
Body Fitting algorithm generates hexahedrons of a Cartesian grid in
|
||||
the internal part of geometry and polyhedrons and other types of
|
||||
elements at the intersection of Cartesian cells with the geometrical
|
||||
boundary.
|
||||
boundary. The algorithm supports construction of
|
||||
:ref:`viscous boundary layers<cartesian_VL_anchor>` (use
|
||||
:ref:`Viscous Layers hypothesis <viscous_layers_anchor>` to define them).
|
||||
|
||||
.. image:: ../images/cartesian3D_sphere.png
|
||||
:align: center
|
||||
@ -15,8 +17,6 @@ boundary.
|
||||
.. centered::
|
||||
A sphere meshed by Body Fitting algorithm
|
||||
|
||||
.. note:: The algorithm creates only 3D elements. To add 2D elements use :ref:`Generate boundary elements <make_2dmesh_from_3d_page>` operation.
|
||||
|
||||
The meshing algorithm is as follows.
|
||||
|
||||
#. Lines of a Cartesian structured grid defined by :ref:`Body Fitting Parameters <cartesian_hyp_anchor>` hypothesis are intersected with the geometry boundary, thus nodes lying on the boundary are found. This step also allows finding out for each node of the Cartesian grid if it is inside or outside the geometry.
|
||||
@ -27,7 +27,17 @@ The meshing algorithm is as follows.
|
||||
* add a hexahedron in the mesh, if all nodes are inside
|
||||
* add a polyhedron or another cell type in the mesh, if some nodes are inside and some outside.
|
||||
|
||||
To apply this algorithm when you define your mesh, select **Body Fitting** in the list of 3D algorithms and add **Body Fitting Parameters** hypothesis. The following dialog will appear:
|
||||
.. _cartesian_VL_anchor:
|
||||
|
||||
**Viscous boundary layers** are constructed as follows:
|
||||
|
||||
* create an offset geometry with offset value equal to full layers thickness by using BRepOffset_MakeOffset OCCT class;
|
||||
* mesh the offset geometry with the Body Fitting algorithm;
|
||||
* create prisms of the layers by projecting boundary nodes of offset geometry onto the boundary of initial geometry.
|
||||
|
||||
.. note:: Viscous layers can't be constructed on geometry with **shared/internal** faces.
|
||||
|
||||
To apply the algorithm when you define your mesh, select **Body Fitting** in the list of 3D algorithms and add **Body Fitting Parameters** hypothesis. The following dialog will appear:
|
||||
|
||||
.. _cartesian_hyp_anchor:
|
||||
|
||||
|
@ -555,12 +555,14 @@
|
||||
group-id ="0"
|
||||
priority ="20"
|
||||
hypos ="CartesianParameters3D"
|
||||
opt-hypos ="ViscousLayers"
|
||||
support-submeshes="false"
|
||||
output ="HEXA"
|
||||
need-hyp ="true"
|
||||
dim ="3">
|
||||
<python-wrap>
|
||||
<algo>Cartesian_3D=BodyFitted()</algo>
|
||||
<hypo>ViscousLayers=ViscousLayers(SetTotalThickness(),SetNumberLayers(),SetStretchFactor(),SetFaces(1),SetFaces(2),SetMethod(),SetGroupName())</hypo>
|
||||
</python-wrap>
|
||||
</algorithm>
|
||||
|
||||
|
@ -45,6 +45,13 @@ SMDS_LinearEdge::SMDS_LinearEdge(const SMDS_MeshNode * node1,
|
||||
myNodes[1] = node2;
|
||||
}
|
||||
|
||||
void SMDS_LinearEdge::Init(const SMDS_MeshNode * node1,
|
||||
const SMDS_MeshNode * node2)
|
||||
{
|
||||
myNodes[0] = node1;
|
||||
myNodes[1] = node2;
|
||||
}
|
||||
|
||||
int SMDS_LinearEdge::NbNodes() const
|
||||
{
|
||||
return 2;
|
||||
|
@ -32,7 +32,8 @@
|
||||
class SMDS_EXPORT SMDS_LinearEdge: public SMDS_CellOfNodes
|
||||
{
|
||||
public:
|
||||
SMDS_LinearEdge(const SMDS_MeshNode * node1, const SMDS_MeshNode * node2);
|
||||
SMDS_LinearEdge(const SMDS_MeshNode * node1=nullptr, const SMDS_MeshNode * node2=nullptr);
|
||||
void Init( const SMDS_MeshNode * node1, const SMDS_MeshNode * node2);
|
||||
|
||||
virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Edge; }
|
||||
virtual SMDSAbs_GeometryType GetGeomType() const { return SMDSGeom_EDGE; }
|
||||
|
@ -7279,6 +7279,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
|
||||
{
|
||||
const SMDS_MeshElement* elem = *eIt;
|
||||
SMESHDS_SubMesh* sm = mesh->MeshElements( elem->getshapeId() );
|
||||
bool marked = elem->isMarked();
|
||||
|
||||
bool keepElem = applyMerge( elem, newElemDefs, nodeNodeMap, /*noHoles=*/false );
|
||||
if ( !keepElem )
|
||||
@ -7315,6 +7316,8 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
|
||||
sm->AddElement( newElem );
|
||||
if ( elem != newElem )
|
||||
ReplaceElemInGroups( elem, newElem, mesh );
|
||||
if ( marked && newElem )
|
||||
newElem->setIsMarked( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1161,6 +1161,18 @@ void SMESHDS_Mesh::UnSetNodeOnShape(const SMDS_MeshNode* aNode)
|
||||
sm->RemoveNode(aNode);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : UnSetElementOnShape
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void SMESHDS_Mesh::UnSetElementOnShape(const SMDS_MeshElement * anElement)
|
||||
{
|
||||
int shapeId = anElement->getshapeId();
|
||||
if (shapeId > 0)
|
||||
if ( SMESHDS_SubMesh* sm = MeshElements( shapeId ))
|
||||
sm->RemoveElement(anElement);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : SetMeshElementOnShape
|
||||
//purpose :
|
||||
|
@ -609,6 +609,7 @@ class SMESHDS_EXPORT SMESHDS_Mesh : public SMDS_Mesh
|
||||
void SetNodeOnEdge (const SMDS_MeshNode * aNode, const TopoDS_Edge& S, double u=0.);
|
||||
void SetNodeOnVertex(const SMDS_MeshNode * aNode, const TopoDS_Vertex & S);
|
||||
void UnSetNodeOnShape(const SMDS_MeshNode * aNode);
|
||||
void UnSetElementOnShape(const SMDS_MeshElement * anElt);
|
||||
void SetMeshElementOnShape (const SMDS_MeshElement * anElt, const TopoDS_Shape & S);
|
||||
void UnSetMeshElementOnShape(const SMDS_MeshElement * anElt, const TopoDS_Shape & S);
|
||||
void SetNodeInVolume(const SMDS_MeshNode * aNode, int Index);
|
||||
|
@ -253,6 +253,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
|
||||
void init(const SMDS_MeshElement* elem, double tolerance);
|
||||
};
|
||||
std::vector< ElementBox* > _elements;
|
||||
//std::string _name;
|
||||
|
||||
typedef ObjectPool< ElementBox > TElementBoxPool;
|
||||
|
||||
@ -340,6 +341,15 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
|
||||
|
||||
if ( child->isLeaf() && child->_elements.capacity() > child->_elements.size() )
|
||||
SMESHUtils::CompactVector( child->_elements );
|
||||
|
||||
// child->_name = _name + char('0' + j);
|
||||
// if ( child->isLeaf() && child->_elements.size() )
|
||||
// {
|
||||
// cout << child->_name << " ";
|
||||
// for ( size_t i = 0; i < child->_elements.size(); ++i )
|
||||
// cout << child->_elements[i]->_element->GetID() << " ";
|
||||
// cout << endl;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -2564,3 +2574,111 @@ SMESH_ElementSearcher* SMESH_MeshAlgos::GetElementSearcher(SMDS_Mesh&
|
||||
{
|
||||
return new SMESH_ElementSearcherImpl( mesh, tolerance, elemIt );
|
||||
}
|
||||
|
||||
|
||||
//================================================================================
|
||||
/*!
|
||||
* \brief Intersect a ray with a convex volume
|
||||
* \param [in] ray - the ray
|
||||
* \param [in] rayLen - ray length
|
||||
* \param [in] vol - the volume
|
||||
* \param [out] tMin - return a ray parameter where the ray enters the volume
|
||||
* \param [out] tMax - return a ray parameter where the ray exit the volume
|
||||
* \param [out] iFacetMin - facet index where the ray enters the volume
|
||||
* \param [out] iFacetMax - facet index where the ray exit the volume
|
||||
* \return bool - true if the ray intersects the volume
|
||||
*/
|
||||
//================================================================================
|
||||
|
||||
bool SMESH_MeshAlgos::IntersectRayVolume( const gp_Ax1& ray,
|
||||
const double rayLen,
|
||||
const SMDS_MeshElement* vol,
|
||||
double & tMin,
|
||||
double & tMax,
|
||||
int & iFacetMin,
|
||||
int & iFacetMax)
|
||||
{
|
||||
/* Ray-Convex Polyhedron Intersection Test by Eric Haines, erich@eye.com
|
||||
*
|
||||
* This test checks the ray against each face of a polyhedron, checking whether
|
||||
* the set of intersection points found for each ray-plane intersection
|
||||
* overlaps the previous intersection results. If there is no overlap (i.e.
|
||||
* no line segment along the ray that is inside the polyhedron), then the
|
||||
* ray misses and returns false; else true.
|
||||
*/
|
||||
SMDS_VolumeTool vTool;
|
||||
if ( !vTool.Set( vol ))
|
||||
return false;
|
||||
|
||||
tMin = -Precision::Infinite() ;
|
||||
tMax = rayLen ;
|
||||
|
||||
/* Test each plane in polyhedron */
|
||||
for ( int iF = 0; iF < vTool.NbFaces(); ++iF )
|
||||
{
|
||||
const SMDS_MeshNode** fNodes = vTool.GetFaceNodes( iF );
|
||||
gp_XYZ normal;
|
||||
vTool.GetFaceNormal( iF,
|
||||
normal.ChangeCoord(1),
|
||||
normal.ChangeCoord(2),
|
||||
normal.ChangeCoord(3) );
|
||||
double D = - ( normal * SMESH_NodeXYZ( fNodes[0] ));
|
||||
|
||||
/* Compute intersection point T and sidedness */
|
||||
double vd = ray.Direction().XYZ() * normal;
|
||||
double vn = ray.Location().XYZ() * normal + D;
|
||||
if ( vd == 0.0 ) {
|
||||
/* ray is parallel to plane - check if ray origin is inside plane's
|
||||
half-space */
|
||||
if ( vn > 0.0 )
|
||||
/* ray origin is outside half-space */
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ray not parallel - get distance to plane */
|
||||
double t = -vn / vd ;
|
||||
if ( vd < 0.0 )
|
||||
{
|
||||
/* front face - T is a near point */
|
||||
if ( t > tMax ) return false;
|
||||
if ( t > tMin ) {
|
||||
/* hit near face */
|
||||
tMin = t ;
|
||||
iFacetMin = iF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* back face - T is a far point */
|
||||
if ( t < tMin ) return false;
|
||||
if ( t < tMax ) {
|
||||
/* hit far face */
|
||||
tMax = t ;
|
||||
iFacetMax = iF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* survived all tests */
|
||||
/* Note: if ray originates on polyhedron, may want to change 0.0 to some
|
||||
* epsilon to avoid intersecting the originating face.
|
||||
*/
|
||||
if ( tMin >= 0.0 ) {
|
||||
/* outside, hitting front face */
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( tMax < rayLen ) {
|
||||
/* inside, hitting back face */
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inside, but back face beyond tmax */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,6 +168,13 @@ namespace SMESH_MeshAlgos
|
||||
const gp_XY& t0, const gp_XY& t1, const gp_XY& t2,
|
||||
double & bc0, double & bc1);
|
||||
|
||||
/*!
|
||||
* \brief Intersect volume by a ray
|
||||
*/
|
||||
bool IntersectRayVolume( const gp_Ax1& ray, const double rayLen,
|
||||
const SMDS_MeshElement* vol,
|
||||
double & tMin, double & tMax,
|
||||
int & iFacetMin, int & iFacetMax);
|
||||
/*!
|
||||
* Return a face having linked nodes n1 and n2 and which is
|
||||
* - not in avoidSet,
|
||||
|
@ -202,6 +202,7 @@ struct SMESH_TNodeXYZ : public gp_XYZ
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void SetXYZ( const gp_XYZ& p ) { SetCoord( p.X(), p.Y(), p.Z() ); }
|
||||
const SMDS_MeshNode* Node() const { return _node; }
|
||||
double Distance(const SMDS_MeshNode* n) const { return (SMESH_TNodeXYZ( n )-*this).Modulus(); }
|
||||
double SquareDistance(const SMDS_MeshNode* n) const { return (SMESH_TNodeXYZ( n )-*this).SquareModulus(); }
|
||||
|
@ -120,6 +120,7 @@ SET(StdMeshers_HEADERS
|
||||
StdMeshers_Projection_1D2D.hxx
|
||||
StdMeshers_CartesianParameters3D.hxx
|
||||
StdMeshers_Cartesian_3D.hxx
|
||||
StdMeshers_Cartesian_VL.hxx
|
||||
StdMeshers_QuadFromMedialAxis_1D2D.hxx
|
||||
StdMeshers_PolygonPerFace_2D.hxx
|
||||
StdMeshers_PolyhedronPerSolid_3D.hxx
|
||||
@ -183,6 +184,7 @@ SET(StdMeshers_SOURCES
|
||||
StdMeshers_Projection_1D2D.cxx
|
||||
StdMeshers_CartesianParameters3D.cxx
|
||||
StdMeshers_Cartesian_3D.cxx
|
||||
StdMeshers_Cartesian_VL.cxx
|
||||
StdMeshers_Adaptive1D.cxx
|
||||
StdMeshers_QuadFromMedialAxis_1D2D.cxx
|
||||
StdMeshers_PolygonPerFace_2D.cxx
|
||||
|
@ -24,21 +24,25 @@
|
||||
//
|
||||
#include "StdMeshers_Cartesian_3D.hxx"
|
||||
#include "StdMeshers_CartesianParameters3D.hxx"
|
||||
|
||||
#include "ObjectPool.hxx"
|
||||
#include "SMDS_MeshNode.hxx"
|
||||
#include "SMDS_VolumeTool.hxx"
|
||||
#include "SMESHDS_Mesh.hxx"
|
||||
#include "SMESH_Block.hxx"
|
||||
#include "SMESH_Comment.hxx"
|
||||
#include "SMESH_ControlsDef.hxx"
|
||||
#include "SMESH_Mesh.hxx"
|
||||
#include "SMESH_MeshAlgos.hxx"
|
||||
#include "SMESH_MeshEditor.hxx"
|
||||
#include "SMESH_MesherHelper.hxx"
|
||||
#include "SMESH_subMesh.hxx"
|
||||
#include "SMESH_subMeshEventListener.hxx"
|
||||
#include "StdMeshers_Cartesian_VL.hxx"
|
||||
#include "StdMeshers_FaceSide.hxx"
|
||||
#include "StdMeshers_ViscousLayers.hxx"
|
||||
|
||||
#include <ObjectPool.hxx>
|
||||
#include <SMDS_LinearEdge.hxx>
|
||||
#include <SMDS_MeshNode.hxx>
|
||||
#include <SMDS_VolumeOfNodes.hxx>
|
||||
#include <SMDS_VolumeTool.hxx>
|
||||
#include <SMESHDS_Mesh.hxx>
|
||||
#include <SMESH_Block.hxx>
|
||||
#include <SMESH_Comment.hxx>
|
||||
#include <SMESH_ControlsDef.hxx>
|
||||
#include <SMESH_Mesh.hxx>
|
||||
#include <SMESH_MeshAlgos.hxx>
|
||||
#include <SMESH_MeshEditor.hxx>
|
||||
#include <SMESH_MesherHelper.hxx>
|
||||
#include <SMESH_subMesh.hxx>
|
||||
#include <SMESH_subMeshEventListener.hxx>
|
||||
|
||||
#include <utilities.h>
|
||||
#include <Utils_ExceptHandlers.hxx>
|
||||
@ -130,7 +134,8 @@ StdMeshers_Cartesian_3D::StdMeshers_Cartesian_3D(int hypId, SMESH_Gen * gen)
|
||||
{
|
||||
_name = "Cartesian_3D";
|
||||
_shapeType = (1 << TopAbs_SOLID); // 1 bit /shape type
|
||||
_compatibleHypothesis.push_back("CartesianParameters3D");
|
||||
_compatibleHypothesis.push_back( "CartesianParameters3D" );
|
||||
_compatibleHypothesis.push_back( StdMeshers_ViscousLayers::GetHypType() );
|
||||
|
||||
_onlyUnaryInput = false; // to mesh all SOLIDs at once
|
||||
_requireDiscreteBoundary = false; // 2D mesh not needed
|
||||
@ -149,19 +154,26 @@ bool StdMeshers_Cartesian_3D::CheckHypothesis (SMESH_Mesh& aMesh,
|
||||
{
|
||||
aStatus = SMESH_Hypothesis::HYP_MISSING;
|
||||
|
||||
const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
|
||||
const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape, /*skipAux=*/false);
|
||||
list <const SMESHDS_Hypothesis* >::const_iterator h = hyps.begin();
|
||||
if ( h == hyps.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_hyp = nullptr;
|
||||
_hypViscousLayers = nullptr;
|
||||
_isComputeOffset = false;
|
||||
|
||||
for ( ; h != hyps.end(); ++h )
|
||||
{
|
||||
if (( _hyp = dynamic_cast<const StdMeshers_CartesianParameters3D*>( *h )))
|
||||
if ( !_hyp && ( _hyp = dynamic_cast<const StdMeshers_CartesianParameters3D*>( *h )))
|
||||
{
|
||||
aStatus = _hyp->IsDefined() ? HYP_OK : HYP_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_hypViscousLayers = dynamic_cast<const StdMeshers_ViscousLayers*>( *h );
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,6 +183,8 @@ bool StdMeshers_Cartesian_3D::CheckHypothesis (SMESH_Mesh& aMesh,
|
||||
namespace
|
||||
{
|
||||
typedef int TGeomID; // IDs of sub-shapes
|
||||
typedef TopTools_ShapeMapHasher TShapeHasher; // non-oriented shape hasher
|
||||
typedef std::array< int, 3 > TIJK;
|
||||
|
||||
const TGeomID theUndefID = 1e+9;
|
||||
|
||||
@ -408,6 +422,11 @@ namespace
|
||||
{
|
||||
_curInd[0] = i; _curInd[1] = j; _curInd[2] = k;
|
||||
}
|
||||
void SetLineIndex(size_t i)
|
||||
{
|
||||
_curInd[_iVar2] = i / _size[_iVar1];
|
||||
_curInd[_iVar1] = i % _size[_iVar1];
|
||||
}
|
||||
void operator++()
|
||||
{
|
||||
if ( ++_curInd[_iVar1] == _size[_iVar1] )
|
||||
@ -419,8 +438,10 @@ namespace
|
||||
size_t LineIndex01 () const { return _curInd[_iVar1] + (_curInd[_iVar2] + 1 )* _size[_iVar1]; }
|
||||
size_t LineIndex11 () const { return (_curInd[_iVar1] + 1 ) + (_curInd[_iVar2] + 1 )* _size[_iVar1]; }
|
||||
void SetIndexOnLine (size_t i) { _curInd[ _iConst ] = i; }
|
||||
bool IsValidIndexOnLine (size_t i) const { return i < _size[ _iConst ]; }
|
||||
size_t NbLines() const { return _size[_iVar1] * _size[_iVar2]; }
|
||||
};
|
||||
struct FaceGridIntersector;
|
||||
// --------------------------------------------------------------------------
|
||||
/*!
|
||||
* \brief Container of GridLine's
|
||||
@ -460,11 +481,16 @@ namespace
|
||||
{
|
||||
return i + j*_coords[0].size() + k*_coords[0].size()*_coords[1].size();
|
||||
}
|
||||
size_t NodeIndex( const TIJK& ijk ) const
|
||||
{
|
||||
return NodeIndex( ijk[0], ijk[1], ijk[2] );
|
||||
}
|
||||
size_t NodeIndexDX() const { return 1; }
|
||||
size_t NodeIndexDY() const { return _coords[0].size(); }
|
||||
size_t NodeIndexDZ() const { return _coords[0].size() * _coords[1].size(); }
|
||||
|
||||
LineIndexer GetLineIndexer(size_t iDir) const;
|
||||
size_t GetLineDir( const GridLine* line, size_t & index ) const;
|
||||
|
||||
E_IntersectPoint* Add( const E_IntersectPoint& ip )
|
||||
{
|
||||
@ -1355,6 +1381,20 @@ namespace
|
||||
s[indices[iDir*3]], s[indices[iDir*3+1]], s[indices[iDir*3+2]]);
|
||||
return li;
|
||||
}
|
||||
//================================================================================
|
||||
/*
|
||||
* Return direction [0,1,2] of a GridLine
|
||||
*/
|
||||
size_t Grid::GetLineDir( const GridLine* line, size_t & index ) const
|
||||
{
|
||||
for ( size_t iDir = 0; iDir < 3; ++iDir )
|
||||
if ( &_lines[ iDir ][0] <= line && line <= &_lines[ iDir ].back() )
|
||||
{
|
||||
index = line - &_lines[ iDir ][0];
|
||||
return iDir;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//=============================================================================
|
||||
/*
|
||||
* Creates GridLine's of the grid
|
||||
@ -1980,6 +2020,8 @@ namespace
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@ -2634,7 +2676,7 @@ namespace
|
||||
if ( _nbFaceIntNodes + _eIntPoints.size() > 0 &&
|
||||
_nbFaceIntNodes + _eIntPoints.size() + _nbCornerNodes > 3)
|
||||
{
|
||||
_intNodes.reserve( 3 * _nbBndNodes + _nbFaceIntNodes + _eIntPoints.size() );
|
||||
_intNodes.reserve( 3 * ( _nbBndNodes + _nbFaceIntNodes + _eIntPoints.size() ));
|
||||
|
||||
// this method can be called in parallel, so use own helper
|
||||
SMESH_MesherHelper helper( *_grid->_helper->GetMesh() );
|
||||
@ -2706,7 +2748,7 @@ namespace
|
||||
// 1) add this->_eIntPoints to _Face::_eIntNodes
|
||||
// 2) fill _intNodes and _vIntNodes
|
||||
//
|
||||
const double tol2 = _grid->_tol * _grid->_tol;
|
||||
const double tol2 = _grid->_tol * _grid->_tol * 4;
|
||||
int facets[3], nbFacets, subEntity;
|
||||
|
||||
for ( int iF = 0; iF < 6; ++iF )
|
||||
@ -6352,6 +6394,27 @@ namespace
|
||||
bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
|
||||
const TopoDS_Shape & theShape)
|
||||
{
|
||||
if ( _hypViscousLayers )
|
||||
{
|
||||
const StdMeshers_ViscousLayers* hypViscousLayers = _hypViscousLayers;
|
||||
_hypViscousLayers = nullptr;
|
||||
|
||||
StdMeshers_Cartesian_VL::ViscousBuilder builder( hypViscousLayers, theMesh, theShape );
|
||||
|
||||
std::string error;
|
||||
TopoDS_Shape offsetShape = builder.MakeOffsetShape( theShape, theMesh, error );
|
||||
if ( offsetShape.IsNull() )
|
||||
throw SALOME_Exception( error );
|
||||
|
||||
SMESH_Mesh* offsetMesh = builder.MakeOffsetMesh();
|
||||
|
||||
this->_isComputeOffset = true;
|
||||
if ( ! this->Compute( *offsetMesh, offsetShape ))
|
||||
return false;
|
||||
|
||||
return builder.MakeViscousLayers( theMesh, theShape );
|
||||
}
|
||||
|
||||
// The algorithm generates the mesh in following steps:
|
||||
|
||||
// 1) Intersection of grid lines with the geometry boundary.
|
||||
@ -6379,6 +6442,11 @@ bool StdMeshers_Cartesian_3D::Compute(SMESH_Mesh & theMesh,
|
||||
grid._toConsiderInternalFaces = _hyp->GetToConsiderInternalFaces();
|
||||
grid._toUseThresholdForInternalFaces = _hyp->GetToUseThresholdForInternalFaces();
|
||||
grid._sizeThreshold = _hyp->GetSizeThreshold();
|
||||
if ( _isComputeOffset )
|
||||
{
|
||||
grid._toAddEdges = true;
|
||||
grid._toCreateFaces = true;
|
||||
}
|
||||
grid.InitGeometry( theShape );
|
||||
|
||||
vector< TopoDS_Shape > faceVec;
|
||||
|
@ -37,8 +37,10 @@
|
||||
* Issue 0021336
|
||||
* Issue #16523: Treatment of internal faces
|
||||
* Issue #17237: Body fitting on sub-mesh
|
||||
* Issue #17015: Body fitting with Viscous Layers
|
||||
*/
|
||||
class StdMeshers_CartesianParameters3D;
|
||||
class StdMeshers_ViscousLayers;
|
||||
|
||||
class STDMESHERS_EXPORT StdMeshers_Cartesian_3D : public SMESH_3D_Algo
|
||||
{
|
||||
@ -61,6 +63,8 @@ public:
|
||||
void setSubmeshesComputed(SMESH_Mesh& aMesh, const TopoDS_Shape& theShape );
|
||||
|
||||
const StdMeshers_CartesianParameters3D* _hyp;
|
||||
const StdMeshers_ViscousLayers* _hypViscousLayers;
|
||||
bool _isComputeOffset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
1056
src/StdMeshers/StdMeshers_Cartesian_VL.cxx
Normal file
1056
src/StdMeshers/StdMeshers_Cartesian_VL.cxx
Normal file
File diff suppressed because it is too large
Load Diff
70
src/StdMeshers/StdMeshers_Cartesian_VL.hxx
Normal file
70
src/StdMeshers/StdMeshers_Cartesian_VL.hxx
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
|
||||
//
|
||||
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
|
||||
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
|
||||
//
|
||||
// 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 : StdMeshers_Cartesian_VL.hxx
|
||||
// Created : Tue May 24 12:32:01 2022
|
||||
// Author : Edward AGAPOV (eap)
|
||||
|
||||
#ifndef __StdMeshers_Cartesian_VL_HXX__
|
||||
#define __StdMeshers_Cartesian_VL_HXX__
|
||||
|
||||
#include <BRepOffset_MakeOffset.hxx>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class StdMeshers_ViscousLayers;
|
||||
class SMESH_Mesh;
|
||||
|
||||
namespace StdMeshers_Cartesian_VL
|
||||
{
|
||||
class ViscousBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
ViscousBuilder( const StdMeshers_ViscousLayers* hypViscousLayers,
|
||||
const SMESH_Mesh & theMesh,
|
||||
const TopoDS_Shape & theShape);
|
||||
~ViscousBuilder();
|
||||
|
||||
TopoDS_Shape MakeOffsetShape(const TopoDS_Shape & theShape,
|
||||
SMESH_Mesh & theMesh,
|
||||
std::string & theError );
|
||||
|
||||
SMESH_Mesh* MakeOffsetMesh();
|
||||
|
||||
bool MakeViscousLayers( SMESH_Mesh & theMesh,
|
||||
const TopoDS_Shape & theShape );
|
||||
|
||||
private:
|
||||
|
||||
TopoDS_Shape getOffsetSubShape( const TopoDS_Shape& S );
|
||||
|
||||
const StdMeshers_ViscousLayers* _hyp;
|
||||
BRepOffset_MakeOffset _makeOffset;
|
||||
SMESH_Mesh* _offsetMesh;
|
||||
TopoDS_Shape _offsetShape;
|
||||
std::set< int > _shapesWVL; // shapes with viscous layers
|
||||
std::map< int, std::vector< int > > _edge2facesWOVL; // EDGE 2 FACEs w/o VL
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -642,13 +642,7 @@ namespace VISCOUS_3D
|
||||
const double T = ( realThickness > 0 ) ? realThickness : GetTotalThickness();
|
||||
const double f = GetStretchFactor();
|
||||
const int N = GetNumberLayers();
|
||||
const double fPowN = pow( f, N );
|
||||
double h0;
|
||||
if ( fPowN - 1 <= numeric_limits<double>::min() )
|
||||
h0 = T / N;
|
||||
else
|
||||
h0 = T * ( f - 1 )/( fPowN - 1 );
|
||||
return h0;
|
||||
return StdMeshers_ViscousLayers::Get1stLayerThickness( T, f, N );
|
||||
}
|
||||
|
||||
bool UseSurfaceNormal() const
|
||||
@ -1452,7 +1446,17 @@ bool StdMeshers_ViscousLayers::IsShapeWithLayers(int shapeIndex) const
|
||||
( std::find( _shapeIds.begin(), _shapeIds.end(), shapeIndex ) != _shapeIds.end() );
|
||||
return IsToIgnoreShapes() ? !isIn : isIn;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
double StdMeshers_ViscousLayers::Get1stLayerThickness( double T, double f, int N )
|
||||
{
|
||||
const double fPowN = pow( f, N );
|
||||
double h0;
|
||||
if ( fPowN - 1 <= numeric_limits<double>::min() )
|
||||
h0 = T / N;
|
||||
else
|
||||
h0 = T * ( f - 1 )/( fPowN - 1 );
|
||||
return h0;
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
SMDS_MeshGroup* StdMeshers_ViscousLayers::CreateGroup( const std::string& theName,
|
||||
SMESH_Mesh& theMesh,
|
||||
|
@ -94,6 +94,11 @@ public:
|
||||
const TopoDS_Shape& aShape,
|
||||
SMESH_Hypothesis::Hypothesis_Status& aStatus);
|
||||
|
||||
// Compute thickness of the 1st layer
|
||||
static double Get1stLayerThickness( double thickTotal,
|
||||
double factor,
|
||||
int nbLayers );
|
||||
|
||||
// Checks if viscous layers should be constructed on a shape
|
||||
bool IsShapeWithLayers(int shapeIndex) const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user