refs 254#: 7.5.5. Mesh generation for semi-analytical boundaries

Add "Chordal Error" parameter to NETGEN
This commit is contained in:
eap 2017-09-25 20:48:41 +03:00
parent 3a149003e1
commit 1a836a25cc
13 changed files with 630 additions and 152 deletions

View File

@ -31,13 +31,19 @@ parameters below. You can select \a Custom to define them manually.
- <b>Growth rate</b> - allows to define how much the linear dimensions of
two adjacent cells can differ (e.g. 0.3 means 30%).
- <b>Nb. Segs per Edge</b> - allows to define the minimum number of
mesh segments in which edges will be split. This parameter is used
only if <b>Limit Size by Surface Curvature</b> is checked.
mesh segments in which edges will be split. Size of elements computed using
this value is trimmed between <b>Min Size</b> and <b>Max Size</b>
bounds. This parameter is used only if <b>Limit Size by Surface
Curvature</b> is checked.
- <b>Nb Segs per Radius</b> - allows to define the size of
mesh segments and mesh faces in which curved edges and surfaces will
be split. This value divided by a radius of curvature gives an element
size at a given point. This parameter is used only if <b>Limit Size by
Surface Curvature</b> is checked.
be split. A radius of local curvature divided by this value gives an element
size at a given point. Element size computed this way is then trimmed
between <b>Min Size</b> and <b>Max Size</b> bounds. This parameter is
used only if <b>Limit Size by Surface Curvature</b> is checked.
- <b>Chordal Error</b> - allows to define the maximum distance between
the generated 2D element and the surface. Size of elements computed using
this criterion is trimmed between <b>Min Size</b> and <b>Max Size</b> bounds.
- <b>Limit Size by Surface Curvature</b> - if this box is checked in,
then size of mesh segments and mesh faces on curved edges and surfaces
is defined using value of <b>Nb Segs per Radius</b> parameter, and
@ -87,6 +93,9 @@ section.<br>
"25 25 0 25 25 200 0.3" means that along the line between points (25,
25, 0) and (25, 25, 200) size of elements should be 0.3.
Sizes defined in the file are trimmed between <b>Min Size</b> and <b>Max Size</b>
bounds.
\image html netgen2d3d_simple.png
<b>NETGEN 2D simple parameters</b> and <b>NETGEN 3D simple

View File

@ -92,6 +92,11 @@ module NETGENPlugin
void SetNbSegPerEdge(in double value);
double GetNbSegPerEdge();
void SetChordalErrorEnabled(in boolean value);
boolean GetChordalErrorEnabled();
void SetChordalError(in double value);
double GetChordalError();
void SetNbSegPerRadius(in double value);
double GetNbSegPerRadius();

View File

@ -177,7 +177,7 @@ QFrame* NETGENPluginGUI_HypothesisCreator::buildFrame()
myFineness = new QComboBox( GroupC1 );
QStringList types;
types << tr( "NETGEN_VERYCOARSE" ) << tr( "NETGEN_COARSE" ) << tr( "NETGEN_MODERATE" ) <<
tr( "NETGEN_FINE" ) << tr( "NETGEN_VERYFINE" ) << tr( "NETGEN_CUSTOM" );
tr( "NETGEN_FINE" ) << tr( "NETGEN_VERYFINE" ) << tr( "NETGEN_CUSTOM" );
myFineness->addItems( types );
aGroupLayout->addWidget( myFineness, row, 1 );
connect( myFineness, SIGNAL( activated( int ) ), this, SLOT( onFinenessChanged() ) );
@ -208,6 +208,19 @@ QFrame* NETGENPluginGUI_HypothesisCreator::buildFrame()
row++;
}
myChordalErrorEnabled = 0;
myChordalError = 0;
if ( myIs2D || !myIsONLY )
{
myChordalErrorEnabled = new QCheckBox( tr( "NETGEN_CHORDAL_ERROR" ), GroupC1 );
aGroupLayout->addWidget( myChordalErrorEnabled, row, 0 );
myChordalError = new SMESHGUI_SpinBox( GroupC1 );
myChordalError->RangeStepAndValidator( COORD_MIN, COORD_MAX, .1, "length_precision" );
aGroupLayout->addWidget( myChordalError, row, 1 );
connect( myChordalErrorEnabled, SIGNAL( stateChanged(int)), SLOT( onChordalErrorEnabled()));
row++;
}
mySurfaceCurvature = 0;
if ( myIs2D || !myIsONLY )
{
@ -337,6 +350,15 @@ void NETGENPluginGUI_HypothesisCreator::retrieveParams() const
else
myNbSegPerRadius->setText( data.myNbSegPerRadiusVar );
}
if ( myChordalError )
{
myChordalErrorEnabled->setChecked( data.myChordalErrorEnabled && data.myChordalError > 0 );
if(data.myChordalErrorVar.isEmpty())
myChordalError->setValue( data.myChordalError > 0 ? data.myChordalError : 0.1 );
else
myChordalError->setText( data.myChordalErrorVar );
myChordalError->setEnabled( myChordalErrorEnabled->isChecked() );
}
if (myAllowQuadrangles)
myAllowQuadrangles->setChecked( data.myAllowQuadrangles );
@ -408,26 +430,28 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromHypo( NetgenHypothesisData
NETGENPlugin::NETGENPlugin_Hypothesis_var h =
NETGENPlugin::NETGENPlugin_Hypothesis::_narrow( initParamsHypothesis() );
//HypothesisData* data = SMESH::GetHypothesisData( hypType() );
h_data.myName = isCreation() ? hypName() : "";
h_data.myMaxSize = h->GetMaxSize();
h_data.myMaxSizeVar = getVariableName("SetMaxSize");
h_data.myMaxSize = h->GetMaxSize();
h_data.myMaxSizeVar = getVariableName("SetMaxSize");
h_data.mySecondOrder = h->GetSecondOrder();
h_data.myOptimize = h->GetOptimize();
h_data.myOptimize = h->GetOptimize();
h_data.myFineness = (int) h->GetFineness();
h_data.myGrowthRate = h->GetGrowthRate();
h_data.myGrowthRateVar = getVariableName("SetGrowthRate");
h_data.myNbSegPerEdge = h->GetNbSegPerEdge();
h_data.myNbSegPerEdgeVar = getVariableName("SetNbSegPerEdge");
h_data.myNbSegPerRadius = h->GetNbSegPerRadius();
h_data.myNbSegPerRadiusVar = getVariableName("SetNbSegPerRadius");
h_data.myMinSize = h->GetMinSize();
h_data.myMinSizeVar = getVariableName("SetMinSize");
h_data.mySurfaceCurvature = h->GetUseSurfaceCurvature();
h_data.myFuseEdges = h->GetFuseEdges();
h_data.myMeshSizeFile = h->GetMeshSizeFile();
h_data.myFineness = (int) h->GetFineness();
h_data.myGrowthRate = h->GetGrowthRate();
h_data.myGrowthRateVar = getVariableName("SetGrowthRate");
h_data.myNbSegPerEdge = h->GetNbSegPerEdge();
h_data.myNbSegPerEdgeVar = getVariableName("SetNbSegPerEdge");
h_data.myNbSegPerRadius = h->GetNbSegPerRadius();
h_data.myNbSegPerRadiusVar = getVariableName("SetNbSegPerRadius");
h_data.myChordalError = h->GetChordalError();
h_data.myChordalErrorVar = getVariableName("SetChordalError");
h_data.myChordalErrorEnabled = h->GetChordalErrorEnabled();
h_data.myMinSize = h->GetMinSize();
h_data.myMinSizeVar = getVariableName("SetMinSize");
h_data.mySurfaceCurvature = h->GetUseSurfaceCurvature();
h_data.myFuseEdges = h->GetFuseEdges();
h_data.myMeshSizeFile = h->GetMeshSizeFile();
//if ( myIs2D )
{
@ -486,6 +510,9 @@ bool NETGENPluginGUI_HypothesisCreator::storeParamsToHypo( const NetgenHypothesi
h->SetVarParameter ( h_data.myNbSegPerRadiusVar.toLatin1().constData(), "SetNbSegPerRadius");
h->SetNbSegPerRadius( h_data.myNbSegPerRadius );
}
h->SetVarParameter ( h_data.myChordalErrorVar.toLatin1().constData(), "SetChordalError");
h->SetChordalError ( h_data.myChordalError );
h->SetChordalErrorEnabled( h_data.myChordalErrorEnabled );
h->SetVarParameter ( h_data.myMinSizeVar.toLatin1().constData(), "SetMinSize");
h->SetMinSize ( h_data.myMinSize );
h->SetUseSurfaceCurvature( h_data.mySurfaceCurvature );
@ -551,8 +578,13 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromWidgets( NetgenHypothesisD
h_data.myNbSegPerEdgeVar = myNbSegPerEdge->text();
if ( myNbSegPerRadius )
h_data.myNbSegPerRadiusVar = myNbSegPerRadius->text();
if ( myChordalError )
{
h_data.myChordalErrorVar = myChordalError->text();
h_data.myChordalError = myChordalError->value();
h_data.myChordalErrorEnabled = myChordalError->isEnabled();
}
if ( myAllowQuadrangles )
h_data.myAllowQuadrangles = myAllowQuadrangles->isChecked();
@ -577,6 +609,11 @@ bool NETGENPluginGUI_HypothesisCreator::readParamsFromWidgets( NetgenHypothesisD
return true;
}
void NETGENPluginGUI_HypothesisCreator::onChordalErrorEnabled()
{
myChordalError->setEnabled( myChordalErrorEnabled->isChecked() );
}
void NETGENPluginGUI_HypothesisCreator::onSurfaceCurvatureChanged()
{
bool isSurfaceCurvature = (mySurfaceCurvature ? mySurfaceCurvature->isChecked() : true);
@ -587,6 +624,11 @@ void NETGENPluginGUI_HypothesisCreator::onSurfaceCurvatureChanged()
myNbSegPerEdge->setEnabled(isCustom && isSurfaceCurvature);
if ( myNbSegPerRadius )
myNbSegPerRadius->setEnabled(isCustom && isSurfaceCurvature);
// if ( myChordalError )
// {
// myChordalError->setEnabled( isSurfaceCurvature );
// myChordalErrorEnabled->setEnabled( isSurfaceCurvature );
// }
}
void NETGENPluginGUI_HypothesisCreator::onFinenessChanged()

View File

@ -44,11 +44,11 @@ class QTableWidget;
typedef struct
{
double myMaxSize, myMinSize, myGrowthRate, myNbSegPerEdge, myNbSegPerRadius;
int myFineness;
bool mySecondOrder, myAllowQuadrangles, myOptimize, mySurfaceCurvature, myFuseEdges;
QString myName, myMeshSizeFile;
QString myMaxSizeVar, myMinSizeVar, myGrowthRateVar, myNbSegPerEdgeVar, myNbSegPerRadiusVar;
double myMaxSize, myMinSize, myGrowthRate, myNbSegPerEdge, myNbSegPerRadius, myChordalError;
int myFineness;
bool mySecondOrder, myAllowQuadrangles, myOptimize, mySurfaceCurvature, myFuseEdges, myChordalErrorEnabled;
QString myName, myMeshSizeFile;
QString myMaxSizeVar, myMinSizeVar, myGrowthRateVar, myNbSegPerEdgeVar, myNbSegPerRadiusVar, myChordalErrorVar;
} NetgenHypothesisData;
/*!
@ -76,6 +76,7 @@ protected:
protected slots:
virtual void onFinenessChanged();
virtual void onChordalErrorEnabled();
virtual void onSurfaceCurvatureChanged();
virtual void onAddLocalSizeOnVertex();
virtual void onAddLocalSizeOnEdge();
@ -102,12 +103,14 @@ private:
SMESHGUI_SpinBox* myGrowthRate;
SMESHGUI_SpinBox* myNbSegPerEdge;
SMESHGUI_SpinBox* myNbSegPerRadius;
QCheckBox* myChordalErrorEnabled;
SMESHGUI_SpinBox* myChordalError;
QCheckBox* myAllowQuadrangles;
QCheckBox* mySurfaceCurvature;
QCheckBox* myFuseEdges;
bool myIs2D;
bool myIsONLY;
bool myIs2D; // 2D or 3D
bool myIsONLY; // one dim or several
QLineEdit* myMeshSizeFile;
QTableWidget* myLocalSizeTable;

View File

@ -91,6 +91,10 @@
<source>NETGEN_SEG_PER_RADIUS</source>
<translation>Nb. Segs per Radius</translation>
</message>
<message>
<source>NETGEN_CHORDAL_ERROR</source>
<translation>Chordal Error</translation>
</message>
<message>
<source>NETGEN_SURFACE_CURVATURE</source>
<translation>Limit Size by Surface Curvature</translation>

View File

@ -221,6 +221,14 @@ class NETGEN_1D2D3D_Algorithm(NETGEN_Algorithm):
if self.Parameters(): self.params.SetNbSegPerRadius(theVal)
pass
## Sets @c ChordalError parameter
# @param theVal new value of the @c ChordalError parameter
def SetChordalError(self, theVal):
if self.Parameters():
self.params.SetChordalError(theVal)
self.params.SetChordalErrorEnabled( theVal > 0 )
pass
## Sets @c QuadAllowed flag
# @param toAllow new value of the @c QuadAllowed parameter (@c True by default)
def SetQuadAllowed(self, toAllow=True):

View File

@ -43,18 +43,20 @@ using namespace std;
NETGENPlugin_Hypothesis::NETGENPlugin_Hypothesis (int hypId, int studyId,
SMESH_Gen * gen)
: SMESH_Hypothesis(hypId, studyId, gen),
_maxSize (GetDefaultMaxSize()),
_minSize (0),
_growthRate (GetDefaultGrowthRate()),
_nbSegPerEdge (GetDefaultNbSegPerEdge()),
_nbSegPerRadius (GetDefaultNbSegPerRadius()),
_fineness (GetDefaultFineness()),
_secondOrder (GetDefaultSecondOrder()),
_optimize (GetDefaultOptimize()),
_localSize (GetDefaultLocalSize()),
_quadAllowed (GetDefaultQuadAllowed()),
_surfaceCurvature(GetDefaultSurfaceCurvature()),
_fuseEdges (GetDefaultFuseEdges())
_maxSize (GetDefaultMaxSize()),
_minSize (0),
_growthRate (GetDefaultGrowthRate()),
_nbSegPerEdge (GetDefaultNbSegPerEdge()),
_nbSegPerRadius (GetDefaultNbSegPerRadius()),
_fineness (GetDefaultFineness()),
_chordalErrorEnabled(GetDefaultChordalError() > 0),
_chordalError (GetDefaultChordalError() ),
_secondOrder (GetDefaultSecondOrder()),
_optimize (GetDefaultOptimize()),
_localSize (GetDefaultLocalSize()),
_quadAllowed (GetDefaultQuadAllowed()),
_surfaceCurvature (GetDefaultSurfaceCurvature()),
_fuseEdges (GetDefaultFuseEdges())
{
_name = "NETGEN_Parameters";
_param_algo_dim = 3;
@ -208,6 +210,34 @@ void NETGENPlugin_Hypothesis::SetNbSegPerRadius(double theVal)
}
}
//=============================================================================
/*!
*
*/
//=============================================================================
void NETGENPlugin_Hypothesis::SetChordalErrorEnabled(bool theVal)
{
if (theVal != _chordalErrorEnabled)
{
_chordalErrorEnabled = theVal;
NotifySubMeshesHypothesisModification();
}
}
//=============================================================================
/*!
*
*/
//=============================================================================
void NETGENPlugin_Hypothesis::SetChordalError(double theVal)
{
if (theVal != _chordalError)
{
_chordalError = theVal;
NotifySubMeshesHypothesisModification();
}
}
//=============================================================================
/*!
*
@ -351,8 +381,8 @@ ostream & NETGENPlugin_Hypothesis::SaveTo(ostream & save)
if (it_sm != _localSize.end()) {
save << " " << "__LOCALSIZE_BEGIN__";
for ( ; it_sm != _localSize.end(); ++it_sm ) {
save << " " << it_sm->first
<< " " << it_sm->second << "%#"; // "%#" is a mark of value end
save << " " << it_sm->first
<< " " << it_sm->second << "%#"; // "%#" is a mark of value end
}
save << " " << "__LOCALSIZE_END__";
}
@ -363,6 +393,8 @@ ostream & NETGENPlugin_Hypothesis::SaveTo(ostream & save)
save << " " << _meshSizeFile.size() << " " << _meshSizeFile;
save << " " << ( _chordalErrorEnabled ? _chordalError : 0. );
return save;
}
@ -476,12 +508,19 @@ istream & NETGENPlugin_Hypothesis::LoadFrom(istream & load)
load.get( &_meshSizeFile[0], is+1 );
}
isOK = static_cast<bool>(load >> val);
if (isOK)
_chordalError = val;
else
load.clear(ios::badbit | load.rdstate());
_chordalErrorEnabled = ( _chordalError > 0 );
return load;
}
//=============================================================================
/*!
*
*
*/
//=============================================================================
ostream & operator <<(ostream & save, NETGENPlugin_Hypothesis & hyp)
@ -491,7 +530,7 @@ ostream & operator <<(ostream & save, NETGENPlugin_Hypothesis & hyp)
//=============================================================================
/*!
*
*
*/
//=============================================================================
istream & operator >>(istream & load, NETGENPlugin_Hypothesis & hyp)
@ -584,6 +623,15 @@ double NETGENPlugin_Hypothesis::GetDefaultNbSegPerRadius()
{
return 2;
}
//=============================================================================
/*!
*
*/
//=============================================================================
double NETGENPlugin_Hypothesis::GetDefaultChordalError()
{
return -1; // disabled by default
}
//=============================================================================
/*!

View File

@ -83,6 +83,11 @@ public:
void SetNbSegPerRadius(double theVal);
double GetNbSegPerRadius() const { return _nbSegPerRadius; }
void SetChordalErrorEnabled(bool value);
double GetChordalErrorEnabled() const { return _chordalErrorEnabled; }
void SetChordalError(double value);
double GetChordalError() const { return _chordalError; }
typedef std::map<std::string, double> TLocalSize;
static TLocalSize GetDefaultLocalSize() { return TLocalSize(); }
void SetLocalSizeOnEntry(const std::string& entry, double localSize);
@ -109,6 +114,7 @@ public:
static double GetDefaultGrowthRate();
static double GetDefaultNbSegPerEdge();
static double GetDefaultNbSegPerRadius();
static double GetDefaultChordalError();
static bool GetDefaultSecondOrder();
static bool GetDefaultOptimize();
static bool GetDefaultQuadAllowed();
@ -141,6 +147,8 @@ private:
double _nbSegPerEdge;
double _nbSegPerRadius;
Fineness _fineness;
bool _chordalErrorEnabled;
double _chordalError;
bool _secondOrder;
bool _optimize;
TLocalSize _localSize;

View File

@ -307,6 +307,36 @@ CORBA::Double NETGENPlugin_Hypothesis_i::GetNbSegPerRadius()
//=============================================================================
void NETGENPlugin_Hypothesis_i::SetChordalErrorEnabled(CORBA::Boolean theValue)
{
if ( isToSetParameter( GetChordalErrorEnabled(), theValue, METH_SetChordalErrorEnabled ))
{
this->GetImpl()->SetChordalErrorEnabled(theValue);
SMESH::TPythonDump() << _this() << ".SetChordalErrorEnabled( " << theValue << " )";
}
}
CORBA::Boolean NETGENPlugin_Hypothesis_i::GetChordalErrorEnabled()
{
return GetImpl()->GetChordalErrorEnabled();
}
void NETGENPlugin_Hypothesis_i::SetChordalError(CORBA::Double theValue)
{
if ( isToSetParameter( GetChordalError(), theValue, METH_SetChordalError ))
{
this->GetImpl()->SetChordalError(theValue);
SMESH::TPythonDump() << _this() << ".SetChordalError( " << SMESH::TVar(theValue) << " )";
}
}
CORBA::Double NETGENPlugin_Hypothesis_i::GetChordalError()
{
return GetImpl()->GetChordalError();
}
//=============================================================================
void NETGENPlugin_Hypothesis_i::SetLocalSizeOnShape(GEOM::GEOM_Object_ptr GeomObj,
CORBA::Double localSize)
throw (SALOME::SALOME_Exception)

View File

@ -79,6 +79,11 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Hypothesis_i:
void SetNbSegPerRadius(CORBA::Double theVal);
CORBA::Double GetNbSegPerRadius();
void SetChordalErrorEnabled(CORBA::Boolean value);
CORBA::Boolean GetChordalErrorEnabled();
void SetChordalError(CORBA::Double value);
CORBA::Double GetChordalError();
void SetLocalSizeOnShape(GEOM::GEOM_Object_ptr GeomObj, CORBA::Double localSize)
throw (SALOME::SALOME_Exception);
void SetLocalSizeOnEntry(const char* entry, CORBA::Double localSize);
@ -109,19 +114,21 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Hypothesis_i:
// to remember whether a parameter is already set (issue 0021364)
enum SettingMethod
{
METH_SetMaxSize = 1,
METH_SetMinSize = 2,
METH_SetSecondOrder = 4,
METH_SetOptimize = 8,
METH_SetFineness = 16,
METH_SetGrowthRate = 32,
METH_SetNbSegPerEdge = 64,
METH_SetNbSegPerRadius = 128,
METH_SetLocalSizeOnEntry = 256,
METH_SetQuadAllowed = METH_SetLocalSizeOnEntry * 2,
METH_SetSurfaceCurvature = METH_SetQuadAllowed * 2,
METH_SetFuseEdges = METH_SetSurfaceCurvature * 2,
METH_LAST = METH_SetFuseEdges
METH_SetMaxSize = 1,
METH_SetMinSize = 2,
METH_SetSecondOrder = 4,
METH_SetOptimize = 8,
METH_SetFineness = 16,
METH_SetGrowthRate = 32,
METH_SetNbSegPerEdge = 64,
METH_SetNbSegPerRadius = 128,
METH_SetLocalSizeOnEntry = 256,
METH_SetQuadAllowed = METH_SetLocalSizeOnEntry * 2,
METH_SetSurfaceCurvature = METH_SetQuadAllowed * 2,
METH_SetFuseEdges = METH_SetSurfaceCurvature * 2,
METH_SetChordalErrorEnabled = METH_SetFuseEdges * 2,
METH_SetChordalError = METH_SetChordalErrorEnabled * 2,
METH_LAST = METH_SetFuseEdges
};
int mySetMethodFlags;

View File

@ -52,21 +52,29 @@
#include <utilities.h>
#include <BRepAdaptor_Surface.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepLProp_SLProps.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <Bnd_B3d.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <NCollection_Map.hxx>
#include <Poly_Triangulation.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_ProgramError.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
#include <TopTools_DataMapOfShapeInteger.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
// Netgen include files
#ifndef OCCGEOMETRY
@ -151,12 +159,14 @@ NETGENPlugin_Mesher::NETGENPlugin_Mesher (SMESH_Mesh* mesh,
_optimize(true),
_fineness(NETGENPlugin_Hypothesis::GetDefaultFineness()),
_isViscousLayers2D(false),
_chordalError(-1), // means disabled
_ngMesh(NULL),
_occgeom(NULL),
_curShapeIndex(-1),
_progressTic(1),
_totalTime(1.0),
_simpleHyp(NULL),
_viscousLayersHyp(NULL),
_ptrToMe(NULL)
{
SetDefaultParameters();
@ -292,32 +302,36 @@ void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_Hypothesis* hyp)
_fineness = hyp->GetFineness();
mparams.uselocalh = hyp->GetSurfaceCurvature();
netgen::merge_solids = hyp->GetFuseEdges();
_chordalError = hyp->GetChordalErrorEnabled() ? hyp->GetChordalError() : -1.;
_simpleHyp = NULL;
// mesh size file
mparams.meshsizefilename= hyp->GetMeshSizeFile().empty() ? 0 : hyp->GetMeshSizeFile().c_str();
SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
SALOMEDS::Study_var myStudy = aStudyMgr->GetStudyByID(hyp->GetStudyId());
if ( !myStudy->_is_nil() )
const NETGENPlugin_Hypothesis::TLocalSize& localSizes = hyp->GetLocalSizesAndEntries();
if ( !localSizes.empty() )
{
const NETGENPlugin_Hypothesis::TLocalSize localSizes = hyp->GetLocalSizesAndEntries();
NETGENPlugin_Hypothesis::TLocalSize::const_iterator it = localSizes.begin();
for ( ; it != localSizes.end() ; it++)
SMESH_Gen_i* smeshGen_i = SMESH_Gen_i::GetSMESHGen();
CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
SALOMEDS::Study_var myStudy = aStudyMgr->GetStudyByID(hyp->GetStudyId());
if ( !myStudy->_is_nil() )
{
std::string entry = (*it).first;
double val = (*it).second;
// --
GEOM::GEOM_Object_var aGeomObj;
SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
if ( !aSObj->_is_nil() ) {
CORBA::Object_var obj = aSObj->GetObject();
aGeomObj = GEOM::GEOM_Object::_narrow(obj);
aSObj->UnRegister();
NETGENPlugin_Hypothesis::TLocalSize::const_iterator it = localSizes.begin();
for ( ; it != localSizes.end() ; it++)
{
std::string entry = (*it).first;
double val = (*it).second;
// --
GEOM::GEOM_Object_var aGeomObj;
SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
if ( !aSObj->_is_nil() ) {
CORBA::Object_var obj = aSObj->GetObject();
aGeomObj = GEOM::GEOM_Object::_narrow(obj);
aSObj->UnRegister();
}
TopoDS_Shape S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
::SetLocalSize(S, val);
}
TopoDS_Shape S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
::SetLocalSize(S, val);
}
}
}
@ -336,6 +350,17 @@ void NETGENPlugin_Mesher::SetParameters(const NETGENPlugin_SimpleHypothesis_2D*
SetDefaultParameters();
}
//================================================================================
/*!
* \brief Store a Viscous Layers hypothesis
*/
//================================================================================
void NETGENPlugin_Mesher::SetParameters(const StdMeshers_ViscousLayers* hyp )
{
_viscousLayersHyp = hyp;
}
//=============================================================================
/*!
* Link - a pair of integer numbers
@ -585,7 +610,8 @@ namespace
void setLocalSize(const TopoDS_Edge& edge,
double size,
netgen::Mesh& mesh)
netgen::Mesh& mesh,
const bool overrideMinH = true)
{
if ( size <= std::numeric_limits<double>::min() )
return;
@ -596,7 +622,7 @@ namespace
TopoDS_Iterator vIt( edge );
if ( !vIt.More() ) return;
gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( vIt.Value() ));
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size );
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH );
}
else
{
@ -606,15 +632,29 @@ namespace
{
Standard_Real u = u1 + delta*i;
gp_Pnt p = curve->Value(u);
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size );
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), size, overrideMinH );
netgen::Point3d pi(p.X(), p.Y(), p.Z());
double resultSize = mesh.GetH(pi);
if ( resultSize - size > 0.1*size )
// netgen does restriction iff oldH/newH > 1.2 (localh.cpp:136)
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), resultSize/1.201 );
NETGENPlugin_Mesher::RestrictLocalSize( mesh, p.XYZ(), resultSize/1.201, overrideMinH );
}
}
}
//================================================================================
/*!
* \brief Return triangle size for a given chordalError and radius of curvature
*/
//================================================================================
double elemSizeForChordalError( double chordalError, double radius )
{
if ( 2 * radius < chordalError )
return 1.5 * radius;
return Sqrt( 3 ) * Sqrt( chordalError * ( 2 * radius - chordalError ));
}
} // namespace
//================================================================================
@ -624,16 +664,19 @@ namespace
//================================================================================
void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
netgen::Mesh& ngMesh )
netgen::Mesh& ngMesh)
{
for(std::map<int,double>::const_iterator it=EdgeId2LocalSize.begin(); it!=EdgeId2LocalSize.end(); it++)
// edges
std::map<int,double>::const_iterator it;
for( it=EdgeId2LocalSize.begin(); it!=EdgeId2LocalSize.end(); it++)
{
int key = (*it).first;
double hi = (*it).second;
const TopoDS_Shape& shape = ShapesWithLocalSize.FindKey(key);
setLocalSize( TopoDS::Edge(shape), hi, ngMesh );
}
for(std::map<int,double>::const_iterator it=VertexId2LocalSize.begin(); it!=VertexId2LocalSize.end(); it++)
// vertices
for(it=VertexId2LocalSize.begin(); it!=VertexId2LocalSize.end(); it++)
{
int key = (*it).first;
double hi = (*it).second;
@ -641,7 +684,8 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex(shape) );
NETGENPlugin_Mesher::RestrictLocalSize( ngMesh, p.XYZ(), hi );
}
for(map<int,double>::const_iterator it=FaceId2LocalSize.begin(); it!=FaceId2LocalSize.end(); it++)
// faces
for(it=FaceId2LocalSize.begin(); it!=FaceId2LocalSize.end(); it++)
{
int key = (*it).first;
double val = (*it).second;
@ -659,7 +703,8 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
ShapesWithControlPoints.insert( key );
}
}
for(map<int,double>::const_iterator it=SolidId2LocalSize.begin(); it!=SolidId2LocalSize.end(); it++)
//solids
for(it=SolidId2LocalSize.begin(); it!=SolidId2LocalSize.end(); it++)
{
int key = (*it).first;
double val = (*it).second;
@ -676,6 +721,146 @@ void NETGENPlugin_Mesher::SetLocalSize( netgen::OCCGeometry& occgeo,
for ( size_t i = 0; i < ControlPoints.size(); ++i )
NETGENPlugin_Mesher::RestrictLocalSize( ngMesh, ControlPoints[i].XYZ(), ControlPoints[i].Size() );
}
return;
}
//================================================================================
/*!
* \brief Restrict local size to achieve a required _chordalError
*/
//================================================================================
void NETGENPlugin_Mesher::SetLocalSizeForChordalError( netgen::OCCGeometry& occgeo,
netgen::Mesh& ngMesh)
{
if ( _chordalError <= 0. )
return;
TopLoc_Location loc;
BRepLProp_SLProps surfProp( 2, 1e-6 );
const double sizeCoef = 0.95;
// find non-planar FACEs with non-constant curvature
std::vector<int> fInd;
for ( int i = 1; i <= occgeo.fmap.Extent(); ++i )
{
const TopoDS_Face& face = TopoDS::Face( occgeo.fmap( i ));
BRepAdaptor_Surface surfAd( face, false );
switch ( surfAd.GetType() )
{
case GeomAbs_Plane:
continue;
case GeomAbs_Cylinder:
case GeomAbs_Sphere:
case GeomAbs_Torus: // constant curvature
{
surfProp.SetSurface( surfAd );
surfProp.SetParameters( 0, 0 );
double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() ));
double size = elemSizeForChordalError( _chordalError, 1 / maxCurv );
occgeo.SetFaceMaxH( i, size * sizeCoef );
// limit size one edges
TopTools_MapOfShape edgeMap;
for ( TopExp_Explorer eExp( face, TopAbs_EDGE ); eExp.More(); eExp.Next() )
if ( edgeMap.Add( eExp.Current() ))
setLocalSize( TopoDS::Edge( eExp.Current() ), size, ngMesh, /*overrideMinH=*/false );
break;
}
default:
Handle(Geom_Surface) surf = BRep_Tool::Surface( face, loc );
if ( GeomLib_IsPlanarSurface( surf ).IsPlanar() )
continue;
fInd.push_back( i );
}
}
// set local size
if ( !fInd.empty() )
{
BRep_Builder b;
TopoDS_Compound allFacesComp;
b.MakeCompound( allFacesComp );
for ( size_t i = 0; i < fInd.size(); ++i )
b.Add( allFacesComp, occgeo.fmap( fInd[i] ));
// copy the shape to avoid spoiling its triangulation
TopoDS_Shape allFacesCompCopy = BRepBuilderAPI_Copy( allFacesComp );
// create triangulation with desired chordal error
BRepMesh_IncrementalMesh( allFacesCompCopy,
_chordalError,
/*isRelative = */Standard_False,
/*theAngDeflection = */ 0.5,
/*isInParallel = */Standard_True);
// loop on FACEs
for ( TopExp_Explorer fExp( allFacesCompCopy, TopAbs_FACE ); fExp.More(); fExp.Next() )
{
const TopoDS_Face& face = TopoDS::Face( fExp.Current() );
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation ( face, loc );
if ( triangulation.IsNull() ) continue;
BRepAdaptor_Surface surf( face, false );
surfProp.SetSurface( surf );
gp_XY uv[3];
gp_XYZ p[3];
double size[3];
for ( int i = 1; i <= triangulation->NbTriangles(); ++i )
{
Standard_Integer n1,n2,n3;
triangulation->Triangles()(i).Get( n1,n2,n3 );
p [0] = triangulation->Nodes()(n1).Transformed(loc).XYZ();
p [1] = triangulation->Nodes()(n2).Transformed(loc).XYZ();
p [2] = triangulation->Nodes()(n3).Transformed(loc).XYZ();
uv[0] = triangulation->UVNodes()(n1).XY();
uv[1] = triangulation->UVNodes()(n2).XY();
uv[2] = triangulation->UVNodes()(n3).XY();
surfProp.SetParameters( uv[0].X(), uv[0].Y() );
if ( !surfProp.IsCurvatureDefined() )
break;
for ( int n = 0; n < 3; ++n ) // get size at triangle nodes
{
surfProp.SetParameters( uv[n].X(), uv[n].Y() );
double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() ));
size[n] = elemSizeForChordalError( _chordalError, 1 / maxCurv );
}
for ( int n1 = 0; n1 < 3; ++n1 ) // limit size along each triangle edge
{
int n2 = ( n1 + 1 ) % 3;
double minSize = size[n1], maxSize = size[n2];
if ( size[n1] > size[n2] )
minSize = size[n2], maxSize = size[n1];
if ( maxSize / minSize < 1.2 ) // netgen ignores size difference < 1.2
{
ngMesh.RestrictLocalHLine ( netgen::Point3d( p[n1].X(), p[n1].Y(), p[n1].Z() ),
netgen::Point3d( p[n2].X(), p[n2].Y(), p[n2].Z() ),
sizeCoef * minSize );
}
else
{
gp_XY uvVec( uv[n2] - uv[n1] );
double len = ( p[n1] - p[n2] ).Modulus();
int nb = int( len / minSize ) + 1;
for ( int j = 0; j <= nb; ++j )
{
double r = double( j ) / nb;
gp_XY uvj = uv[n1] + r * uvVec;
surfProp.SetParameters( uvj.X(), uvj.Y() );
double maxCurv = Max( Abs( surfProp.MaxCurvature()), Abs( surfProp.MinCurvature() ));
double h = elemSizeForChordalError( _chordalError, 1 / maxCurv );
const gp_Pnt& pj = surfProp.Value();
netgen::Point3d ngP( pj.X(), pj.Y(), pj.Z());
ngMesh.RestrictLocalH( ngP, h * sizeCoef );
}
}
}
}
}
}
}
//================================================================================
@ -808,7 +993,7 @@ double NETGENPlugin_Mesher::GetDefaultMinSize(const TopoDS_Shape& geom,
}
else
{
minh = 3 * sqrt( minh ); // triangulation for visualization is rather fine
minh = sqrt( minh ); // triangulation for visualization is rather fine
//cout << "TRIANGULATION minh = " <<minh << endl;
}
if ( minh > 0.5 * maxSize )
@ -926,7 +1111,8 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
// get all nodes from connected <edges>
const bool isQuad = smDS->IsQuadratic();
StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad );
//StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad, &helper ); -- master
StdMeshers_FaceSide fSide( face, edges, _mesh, isForwad, isQuad ); // -- V8_2_BR
const vector<UVPtStruct>& points = fSide.GetUVPtStruct();
if ( points.empty() )
return false; // invalid node params?
@ -1054,13 +1240,6 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
// Find solids the geomFace bounds
int solidID1 = 0, solidID2 = 0;
StdMeshers_QuadToTriaAdaptor* quadAdaptor =
dynamic_cast<StdMeshers_QuadToTriaAdaptor*>( proxyMesh.get() );
if ( quadAdaptor )
{
solidID1 = occgeom.somap.FindIndex( quadAdaptor->GetShape() );
}
else
{
PShapeIteratorPtr solidIt = helper.GetAncestors( geomFace, *sm->GetFather(), TopAbs_SOLID);
while ( const TopoDS_Shape * solid = solidIt->next() )
@ -1070,6 +1249,81 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
else solidID1 = id;
}
}
if ( proxyMesh && proxyMesh->GetProxySubMesh( geomFace ))
{
// if a proxy sub-mesh contains temporary faces, then these faces
// should be used to mesh only one SOLID
bool hasTmp = false;
smDS = proxyMesh->GetSubMesh( geomFace );
SMDS_ElemIteratorPtr faces = smDS->GetElements();
while ( faces->more() )
{
const SMDS_MeshElement* f = faces->next();
if ( proxyMesh->IsTemporary( f ))
{
hasTmp = true;
std::vector<const SMDS_MeshNode*> fNodes( f->begin_nodes(), f->end_nodes() );
std::vector<const SMDS_MeshElement*> vols;
if ( _mesh->GetMeshDS()->GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) == 1 )
{
int geomID = vols[0]->getshapeId();
const TopoDS_Shape& solid = helper.GetMeshDS()->IndexToShape( geomID );
if ( !solid.IsNull() )
solidID1 = occgeom.somap.FindIndex ( solid );
solidID2 = 0;
break;
}
}
}
// exclude faces generated by NETGEN from computation of 3D mesh
const int fID = occgeom.fmap.FindIndex( geomFace );
if ( !hasTmp ) // shrunk mesh
{
// move netgen points according to moved nodes
SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true);
while ( smIt->more() )
{
SMESH_subMesh* sub = smIt->next();
if ( !sub->GetSubMeshDS() ) continue;
SMDS_NodeIteratorPtr nodeIt = sub->GetSubMeshDS()->GetNodes();
while ( nodeIt->more() )
{
const SMDS_MeshNode* n = nodeIt->next();
int ngID = ngNodeId( n, ngMesh, nodeNgIdMap );
netgen::MeshPoint& ngPoint = ngMesh.Point( ngID );
ngPoint(0) = n->X();
ngPoint(1) = n->Y();
ngPoint(2) = n->Z();
}
}
// remove faces near boundary to avoid their overlapping
// with shrunk faces
for ( int i = 1; i <= ngMesh.GetNSE(); ++i )
{
const netgen::Element2d& elem = ngMesh.SurfaceElement(i);
if ( elem.GetIndex() == fID )
{
for ( int iN = 0; iN < elem.GetNP(); ++iN )
if ( ngMesh[ elem[ iN ]].Type() != netgen::SURFACEPOINT )
{
ngMesh.DeleteSurfaceElement( i );
break;
}
}
}
}
//if ( hasTmp )
{
faceNgID++;
ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID,/*solid1=*/0,/*solid2=*/0,0 ));
for (int i = 1; i <= ngMesh.GetNSE(); ++i )
{
const netgen::Element2d& elem = ngMesh.SurfaceElement(i);
if ( elem.GetIndex() == fID )
const_cast< netgen::Element2d& >( elem ).SetIndex( faceNgID );
}
}
}
// Add ng face descriptors of meshed faces
faceNgID++;
ngMesh.AddFaceDescriptor( netgen::FaceDescriptor( faceNgID, solidID1, solidID2, 0 ));
@ -1112,8 +1366,6 @@ bool NETGENPlugin_Mesher::FillNgMesh(netgen::OCCGeometry& occgeom,
cout << "SMESH face " << helper.GetMeshDS()->ShapeToIndex( geomFace )
<< " internal="<<isInternalFace << endl;
#endif
if ( proxyMesh )
smDS = proxyMesh->GetSubMesh( geomFace );
SMDS_ElemIteratorPtr faces = smDS->GetElements();
while ( faces->more() )
@ -1430,10 +1682,15 @@ namespace
int ngIdCloseN; //!< ng id of closest node of the closest 2d mesh element
};
inline double dist2(const netgen::MeshPoint& p1, const netgen::MeshPoint& p2)
inline double dist2( const netgen::MeshPoint& p1, const netgen::MeshPoint& p2 )
{
return gp_Pnt( NGPOINT_COORDS(p1)).SquareDistance( gp_Pnt( NGPOINT_COORDS(p2)));
}
// inline double dist2(const netgen::MeshPoint& p, const SMDS_MeshNode* n )
// {
// return gp_Pnt( NGPOINT_COORDS(p)).SquareDistance( SMESH_NodeXYZ(n));
// }
}
//================================================================================
@ -2136,13 +2393,35 @@ int NETGENPlugin_Mesher::FillSMesh(const netgen::OCCGeometry& occgeo,
if ( quadHelper && !quadHelper->GetIsQuadratic() && quadHelper->GetTLinkNodeMap().empty() )
quadHelper = 0;
int i, nbInitNod = initState._nbNodes;
if ( initState._elementsRemoved )
{
// PAL23427. Update nodeVec to track removal of netgen free points as a result
// of removal of faces in FillNgMesh() in the case of a shrunk sub-mesh
int ngID, nodeVecSize = nodeVec.size();
const double eps = std::numeric_limits<double>::min();
for ( ngID = i = 1; i < nodeVecSize; ++ngID, ++i )
{
gp_Pnt ngPnt( NGPOINT_COORDS( ngMesh.Point( ngID )));
gp_Pnt node ( SMESH_NodeXYZ ( nodeVec[ i ]));
if ( ngPnt.SquareDistance( node ) < eps )
{
nodeVec[ ngID ] = nodeVec[ i ];
}
else
{
--ngID;
}
}
nodeVec.resize( ngID );
nbInitNod = ngID - 1;
}
// -------------------------------------
// Create and insert nodes into nodeVec
// -------------------------------------
nodeVec.resize( nbNod + 1 );
int i, nbInitNod = initState._nbNodes;
for (i = nbInitNod+1; i <= nbNod; ++i )
for ( i = nbInitNod+1; i <= nbNod; ++i )
{
const netgen::MeshPoint& ngPoint = ngMesh.Point(i);
SMDS_MeshNode* node = NULL;
@ -2503,8 +2782,6 @@ bool NETGENPlugin_Mesher::Compute()
SMESH_MesherHelper quadHelper( *_mesh );
quadHelper.SetIsQuadratic( mparams.secondorder );
static string debugFile = "/tmp/ngMesh.py"; /* to call toPython( _ngMesh, debugFile )
while debugging netgen */
// -------------------------
// Prepare OCC geometry
// -------------------------
@ -2621,6 +2898,7 @@ bool NETGENPlugin_Mesher::Compute()
{
// Local size on shapes
SetLocalSize( occgeo, *_ngMesh );
SetLocalSizeForChordalError( occgeo, *_ngMesh );
}
// Precompute internal edges (issue 0020676) in order to
@ -2791,7 +3069,8 @@ bool NETGENPlugin_Mesher::Compute()
helper.SetSubShape( F );
TSideVector wires =
StdMeshers_FaceSide::GetFaceWires( F, *_mesh, /*skipMediumNodes=*/true,
error, viscousMesh );
error, viscousMesh ); // -- V8_2_BR
// error, &helper, viscousMesh ); -- master
error = AddSegmentsToMesh( *_ngMesh, occgeo, wires, helper, nodeVec );
if ( !error ) error = SMESH_ComputeError::New();
@ -2835,37 +3114,58 @@ bool NETGENPlugin_Mesher::Compute()
// generate volume mesh
// ---------------------
// Fill _ngMesh with nodes and faces of computed 2D submeshes
if ( !err && _isVolume && ( !meshedSM[ MeshDim_2D ].empty() || mparams.quad ))
if ( !err && _isVolume &&
( !meshedSM[ MeshDim_2D ].empty() || mparams.quad || _viscousLayersHyp ))
{
// load SMESH with computed segments and faces
FillSMesh( occgeo, *_ngMesh, initState, *_mesh, nodeVec, comment, &quadHelper );
// compute prismatic boundary volumes
int nbQuad = _mesh->NbQuadrangles();
SMESH_ProxyMesh::Ptr viscousMesh;
if ( _viscousLayersHyp )
{
viscousMesh = _viscousLayersHyp->Compute( *_mesh, _shape );
if ( !viscousMesh )
return false;
}
// compute pyramids on quadrangles
SMESH_ProxyMesh::Ptr proxyMesh;
if ( _mesh->NbQuadrangles() > 0 )
vector<SMESH_ProxyMesh::Ptr> pyramidMeshes( occgeo.somap.Extent() );
if ( nbQuad > 0 )
for ( int iS = 1; iS <= occgeo.somap.Extent(); ++iS )
{
StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
proxyMesh.reset( Adaptor );
int nbPyrams = _mesh->NbPyramids();
Adaptor->Compute( *_mesh, occgeo.somap(iS) );
if ( nbPyrams != _mesh->NbPyramids() )
{
list< SMESH_subMesh* > quadFaceSM;
for (TopExp_Explorer face(occgeo.somap(iS), TopAbs_FACE); face.More(); face.Next())
if ( Adaptor->GetProxySubMesh( face.Current() ))
{
quadFaceSM.push_back( _mesh->GetSubMesh( face.Current() ));
meshedSM[ MeshDim_2D ].remove( quadFaceSM.back() );
}
FillNgMesh(occgeo, *_ngMesh, nodeVec, quadFaceSM, &quadHelper, proxyMesh);
}
StdMeshers_QuadToTriaAdaptor* adaptor = new StdMeshers_QuadToTriaAdaptor;
pyramidMeshes[ iS-1 ].reset( adaptor );
bool ok = adaptor->Compute( *_mesh, occgeo.somap(iS), viscousMesh.get() );
if ( !ok )
return false;
}
// add proxy faces to NG mesh
list< SMESH_subMesh* > viscousSM;
for ( int iS = 1; iS <= occgeo.somap.Extent(); ++iS )
{
list< SMESH_subMesh* > quadFaceSM;
for (TopExp_Explorer face(occgeo.somap(iS), TopAbs_FACE); face.More(); face.Next())
if ( pyramidMeshes[iS-1] && pyramidMeshes[iS-1]->GetProxySubMesh( face.Current() ))
{
quadFaceSM.push_back( _mesh->GetSubMesh( face.Current() ));
meshedSM[ MeshDim_2D ].remove( quadFaceSM.back() );
}
else if ( viscousMesh && viscousMesh->GetProxySubMesh( face.Current() ))
{
viscousSM.push_back( _mesh->GetSubMesh( face.Current() ));
meshedSM[ MeshDim_2D ].remove( viscousSM.back() );
}
if ( !quadFaceSM.empty() )
FillNgMesh(occgeo, *_ngMesh, nodeVec, quadFaceSM, &quadHelper, pyramidMeshes[iS-1]);
}
if ( !viscousSM.empty() )
FillNgMesh(occgeo, *_ngMesh, nodeVec, viscousSM, &quadHelper, viscousMesh );
// fill _ngMesh with faces of sub-meshes
err = ! ( FillNgMesh(occgeo, *_ngMesh, nodeVec, meshedSM[ MeshDim_2D ], &quadHelper));
initState = NETGENPlugin_ngMeshInfo(_ngMesh);
//toPython( _ngMesh, "/tmp/ngPython.py");
initState = NETGENPlugin_ngMeshInfo(_ngMesh, /*checkRemovedElems=*/true);
// toPython( _ngMesh );
}
if (!err && _isVolume)
{
@ -3166,25 +3466,25 @@ bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap)
sm->GetComputeError().reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED ));
return false;
}
if ( _simpleHyp )
{
// Pass 1D simple parameters to NETGEN
// --------------------------------
int nbSeg = _simpleHyp->GetNumberOfSegments();
double segSize = _simpleHyp->GetLocalLength();
for ( int iE = 1; iE <= occgeo.emap.Extent(); ++iE )
{
const TopoDS_Edge& e = TopoDS::Edge( occgeo.emap(iE));
if ( nbSeg )
segSize = SMESH_Algo::EdgeLength( e ) / ( nbSeg - 0.4 );
setLocalSize( e, segSize, *ngMesh );
}
}
else // if ( ! _simpleHyp )
{
// Local size on shapes
SetLocalSize( occgeo, *ngMesh );
}
// if ( _simpleHyp )
// {
// // Pass 1D simple parameters to NETGEN
// // --------------------------------
// int nbSeg = _simpleHyp->GetNumberOfSegments();
// double segSize = _simpleHyp->GetLocalLength();
// for ( int iE = 1; iE <= occgeo.emap.Extent(); ++iE )
// {
// const TopoDS_Edge& e = TopoDS::Edge( occgeo.emap(iE));
// if ( nbSeg )
// segSize = SMESH_Algo::EdgeLength( e ) / ( nbSeg - 0.4 );
// setLocalSize( e, segSize, *ngMesh );
// }
// }
// else // if ( ! _simpleHyp )
// {
// // Local size on shapes
// SetLocalSize( occgeo, *ngMesh );
// }
// calculate total nb of segments and length of edges
double fullLen = 0.0;
int fullNbSeg = 0;
@ -3492,7 +3792,7 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh )
ofstream outfile( pyFile, ios::out );
if ( !outfile ) return;
outfile << "import SMESH" << endl
outfile << "import salome, SMESH" << endl
<< "from salome.smesh import smeshBuilder" << endl
<< "smesh = smeshBuilder.New(salome.myStudy)" << endl
<< "mesh = smesh.Mesh()" << endl << endl;
@ -3556,8 +3856,9 @@ void NETGENPlugin_Mesher::toPython( const netgen::Mesh* ngMesh )
*/
//================================================================================
NETGENPlugin_ngMeshInfo::NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh):
_copyOfLocalH(0)
NETGENPlugin_ngMeshInfo::NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh,
bool checkRemovedElems):
_elementsRemoved( false ), _copyOfLocalH(0)
{
if ( ngMesh )
{
@ -3565,6 +3866,10 @@ NETGENPlugin_ngMeshInfo::NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh):
_nbSegments = ngMesh->GetNSeg();
_nbFaces = ngMesh->GetNSE();
_nbVolumes = ngMesh->GetNE();
if ( checkRemovedElems )
for ( int i = 1; i <= ngMesh->GetNSE() && !_elementsRemoved; ++i )
_elementsRemoved = ngMesh->SurfaceElement(i).IsDeleted();
}
else
{

View File

@ -46,14 +46,15 @@ namespace nglib {
#include <vector>
#include <set>
class NETGENPlugin_Hypothesis;
class NETGENPlugin_Internals;
class NETGENPlugin_SimpleHypothesis_2D;
class SMESHDS_Mesh;
class SMESH_Comment;
class SMESH_Mesh;
class SMESH_MesherHelper;
class StdMeshers_ViscousLayers;
class TopoDS_Shape;
class NETGENPlugin_Hypothesis;
class NETGENPlugin_SimpleHypothesis_2D;
class NETGENPlugin_Internals;
namespace netgen {
class OCCGeometry;
class Mesh;
@ -66,9 +67,10 @@ namespace netgen {
struct NETGENPlugin_ngMeshInfo
{
int _nbNodes, _nbSegments, _nbFaces, _nbVolumes;
int _nbNodes, _nbSegments, _nbFaces, _nbVolumes;
bool _elementsRemoved; // case where netgen can remove free nodes
char* _copyOfLocalH;
NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh=0);
NETGENPlugin_ngMeshInfo( netgen::Mesh* ngMesh=0, bool checkRemovedElems=false );
void transferLocalH( netgen::Mesh* fromMesh, netgen::Mesh* toMesh );
void restoreLocalH ( netgen::Mesh* ngMesh);
};
@ -120,7 +122,10 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
void SetParameters(const NETGENPlugin_Hypothesis* hyp);
void SetParameters(const NETGENPlugin_SimpleHypothesis_2D* hyp);
void SetParameters(const StdMeshers_ViscousLayers* hyp );
void SetViscousLayers2DAssigned(bool isAssigned) { _isViscousLayers2D = isAssigned; }
void SetLocalSizeForChordalError( netgen::OCCGeometry& occgeo, netgen::Mesh& ngMesh );
static void SetLocalSize( netgen::OCCGeometry& occgeo, netgen::Mesh& ngMesh );
bool Compute();
@ -201,6 +206,7 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
bool _optimize;
int _fineness;
bool _isViscousLayers2D;
double _chordalError;
netgen::Mesh* _ngMesh;
netgen::OCCGeometry* _occgeom;
@ -210,6 +216,7 @@ class NETGENPLUGIN_EXPORT NETGENPlugin_Mesher
volatile double _totalTime;
const NETGENPlugin_SimpleHypothesis_2D * _simpleHyp;
const StdMeshers_ViscousLayers* _viscousLayersHyp;
// a pointer to NETGENPlugin_Mesher* field of the holder, that will be
// nullified at destruction of this

View File

@ -319,6 +319,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh,
// set local size defined on shapes
aMesher.SetLocalSize( occgeoComm, *ngMeshes[0] );
aMesher.SetLocalSizeForChordalError( occgeoComm, *ngMeshes[0] );
try {
ngMeshes[0]->LoadLocalMeshSize( mparam.meshsizefilename );
} catch (NgException & ex) {
@ -460,6 +461,7 @@ bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh,
bb.Increase (bb.Diam()/10);
ngMesh->SetLocalH (bb.PMin(), bb.PMax(), mparam.grading);
aMesher.SetLocalSize( occgeom, *ngMesh );
aMesher.SetLocalSizeForChordalError( occgeoComm, *ngMesh );
try {
ngMesh->LoadLocalMeshSize( mparam.meshsizefilename );
} catch (NgException & ex) {