mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-24 21:10:33 +05:00
Merge branch 'boundarylayer' into 'master'
modernize and improve GenerateBoundaryLayer See merge request jschoeberl/netgen!318
This commit is contained in:
commit
319b6dc600
File diff suppressed because it is too large
Load Diff
@ -12,18 +12,16 @@ class BoundaryLayerParameters
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// parameters by Philippose ..
|
// parameters by Philippose ..
|
||||||
NgArray<int> surfid;
|
Array<int> surfid;
|
||||||
NgArray<double> heights;
|
Array<double> heights;
|
||||||
NgArray<double> new_matnrs;
|
Array<size_t> new_matnrs;
|
||||||
int prismlayers = 1;
|
BitArray domains;
|
||||||
int bulk_matnr = 1;
|
bool outside = false; // set the boundary layer on the outside
|
||||||
int new_matnr = 1;
|
bool grow_edges = false;
|
||||||
double hfirst = 0.01;
|
|
||||||
double growthfactor = 1;
|
|
||||||
bool optimize = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DLL_HEADER extern void GenerateBoundaryLayer (Mesh & mesh, BoundaryLayerParameters & blp);
|
DLL_HEADER void GenerateBoundaryLayer (Mesh & mesh,
|
||||||
|
const BoundaryLayerParameters & blp);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#ifdef NG_PYTHON
|
#ifdef NG_PYTHON
|
||||||
|
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include <../general/ngpython.hpp>
|
#include <../general/ngpython.hpp>
|
||||||
#include <core/python_ngcore.hpp>
|
#include <core/python_ngcore.hpp>
|
||||||
#include "python_mesh.hpp"
|
#include "python_mesh.hpp"
|
||||||
@ -885,12 +887,13 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
|
|||||||
meshingparameter_description.c_str(),
|
meshingparameter_description.c_str(),
|
||||||
py::call_guard<py::gil_scoped_release>())
|
py::call_guard<py::gil_scoped_release>())
|
||||||
|
|
||||||
.def ("OptimizeVolumeMesh", [](Mesh & self)
|
.def ("OptimizeVolumeMesh", [](Mesh & self, MeshingParameters* pars)
|
||||||
{
|
{
|
||||||
MeshingParameters mp;
|
MeshingParameters mp;
|
||||||
mp.optsteps3d = 5;
|
if(pars) mp = *pars;
|
||||||
|
else mp.optsteps3d = 5;
|
||||||
OptimizeVolume (mp, self);
|
OptimizeVolume (mp, self);
|
||||||
},py::call_guard<py::gil_scoped_release>())
|
}, py::arg("mp"), py::call_guard<py::gil_scoped_release>())
|
||||||
|
|
||||||
.def ("OptimizeMesh2d", [](Mesh & self)
|
.def ("OptimizeMesh2d", [](Mesh & self)
|
||||||
{
|
{
|
||||||
@ -929,63 +932,112 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
|
|||||||
|
|
||||||
.def ("BuildSearchTree", &Mesh::BuildElementSearchTree,py::call_guard<py::gil_scoped_release>())
|
.def ("BuildSearchTree", &Mesh::BuildElementSearchTree,py::call_guard<py::gil_scoped_release>())
|
||||||
|
|
||||||
.def ("BoundaryLayer", FunctionPointer
|
.def ("BoundaryLayer", [](Mesh & self, variant<string, int> boundary,
|
||||||
([](Mesh & self, int bc, py::list thicknesses, int volnr, py::list materials)
|
variant<double, py::list> thickness,
|
||||||
|
variant<string, py::list> material,
|
||||||
|
variant<string, int> domain, bool outside,
|
||||||
|
bool grow_edges)
|
||||||
{
|
{
|
||||||
int n = py::len(thicknesses);
|
|
||||||
BoundaryLayerParameters blp;
|
BoundaryLayerParameters blp;
|
||||||
|
if(int* bc = get_if<int>(&boundary); bc)
|
||||||
for (int i = 1; i <= self.GetNFD(); i++)
|
|
||||||
if (self.GetFaceDescriptor(i).BCProperty() == bc)
|
|
||||||
blp.surfid.Append (i);
|
|
||||||
|
|
||||||
cout << "add layer at surfaces: " << blp.surfid << endl;
|
|
||||||
|
|
||||||
blp.prismlayers = n;
|
|
||||||
blp.growthfactor = 1.0;
|
|
||||||
|
|
||||||
// find max domain nr
|
|
||||||
int maxind = 0;
|
|
||||||
for (ElementIndex ei = 0; ei < self.GetNE(); ei++)
|
|
||||||
maxind = max (maxind, self[ei].GetIndex());
|
|
||||||
cout << "maxind = " << maxind << endl;
|
|
||||||
for ( int i=0; i<n; i++ )
|
|
||||||
{
|
{
|
||||||
blp.heights.Append( py::extract<double>(thicknesses[i])()) ;
|
for (int i = 1; i <= self.GetNFD(); i++)
|
||||||
blp.new_matnrs.Append( maxind+1+i );
|
if(self.GetFaceDescriptor(i).BCProperty() == *bc)
|
||||||
self.SetMaterial (maxind+1+i, py::extract<string>(materials[i])().c_str());
|
blp.surfid.Append (i);
|
||||||
}
|
}
|
||||||
blp.bulk_matnr = volnr;
|
else
|
||||||
|
{
|
||||||
|
regex pattern(*get_if<string>(&boundary));
|
||||||
|
for(int i = 1; i<=self.GetNFD(); i++)
|
||||||
|
if(regex_match(self.GetFaceDescriptor(i).GetBCName(), pattern))
|
||||||
|
blp.surfid.Append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(double* pthickness = get_if<double>(&thickness); pthickness)
|
||||||
|
{
|
||||||
|
blp.heights.Append(*pthickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto thicknesses = *get_if<py::list>(&thickness);
|
||||||
|
for(auto val : thicknesses)
|
||||||
|
blp.heights.Append(val.cast<double>());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prismlayers = blp.heights.Size();
|
||||||
|
auto first_new_mat = self.GetNDomains() + 1;
|
||||||
|
auto max_dom_nr = first_new_mat;
|
||||||
|
if(string* pmaterial = get_if<string>(&material); pmaterial)
|
||||||
|
{
|
||||||
|
self.SetMaterial(first_new_mat, *pmaterial);
|
||||||
|
for(auto i : Range(prismlayers))
|
||||||
|
blp.new_matnrs.Append(first_new_mat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto materials = *get_if<py::list>(&material);
|
||||||
|
if(py::len(materials) != prismlayers)
|
||||||
|
throw Exception("Length of thicknesses and materials must be same!");
|
||||||
|
for(auto i : Range(prismlayers))
|
||||||
|
{
|
||||||
|
self.SetMaterial(first_new_mat+i, materials[i].cast<string>());
|
||||||
|
blp.new_matnrs.Append(first_new_mat + i);
|
||||||
|
}
|
||||||
|
max_dom_nr += prismlayers-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
blp.domains.SetSize(max_dom_nr + 1); // one based
|
||||||
|
blp.domains.Clear();
|
||||||
|
if(string* pdomain = get_if<string>(&domain); pdomain)
|
||||||
|
{
|
||||||
|
regex pattern(*pdomain);
|
||||||
|
for(auto i : Range(1, first_new_mat))
|
||||||
|
if(regex_match(self.GetMaterial(i), pattern))
|
||||||
|
blp.domains.SetBit(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto idomain = *get_if<int>(&domain);
|
||||||
|
blp.domains.SetBit(idomain);
|
||||||
|
}
|
||||||
|
// bits for new domains must be set
|
||||||
|
if(!outside)
|
||||||
|
for(auto i : Range(first_new_mat, max_dom_nr+1))
|
||||||
|
blp.domains.SetBit(i);
|
||||||
|
|
||||||
|
blp.outside = outside;
|
||||||
|
blp.grow_edges = grow_edges;
|
||||||
|
|
||||||
GenerateBoundaryLayer (self, blp);
|
GenerateBoundaryLayer (self, blp);
|
||||||
}
|
self.UpdateTopology();
|
||||||
))
|
}, py::arg("boundary"), py::arg("thickness"), py::arg("material"),
|
||||||
|
py::arg("domains") = ".*", py::arg("outside") = false,
|
||||||
|
py::arg("grow_edges") = false,
|
||||||
|
R"delimiter(
|
||||||
|
Add boundary layer to mesh.
|
||||||
|
|
||||||
.def ("BoundaryLayer", FunctionPointer
|
Parameters
|
||||||
([](Mesh & self, int bc, double thickness, int volnr, string material)
|
----------
|
||||||
{
|
|
||||||
BoundaryLayerParameters blp;
|
|
||||||
|
|
||||||
for (int i = 1; i <= self.GetNFD(); i++)
|
boundary : string or int
|
||||||
if (self.GetFaceDescriptor(i).BCProperty() == bc)
|
Boundary name or number.
|
||||||
blp.surfid.Append (i);
|
|
||||||
|
|
||||||
cout << "add layer at surfaces: " << blp.surfid << endl;
|
thickness : float or List[float]
|
||||||
|
Thickness of boundary layer(s).
|
||||||
|
|
||||||
blp.prismlayers = 1;
|
material : str or List[str]
|
||||||
blp.hfirst = thickness;
|
Material name of boundary layer(s).
|
||||||
blp.growthfactor = 1.0;
|
|
||||||
|
|
||||||
// find max domain nr
|
domain : str or int
|
||||||
int maxind = 0;
|
Regexp for domain boundarylayer is going into.
|
||||||
for (ElementIndex ei = 0; ei < self.GetNE(); ei++)
|
|
||||||
maxind = max (maxind, self[ei].GetIndex());
|
outside : bool = False
|
||||||
cout << "maxind = " << maxind << endl;
|
If true add the layer on the outside
|
||||||
self.SetMaterial (maxind+1, material.c_str());
|
|
||||||
blp.new_matnr = maxind+1;
|
grow_edges : bool = False
|
||||||
blp.bulk_matnr = volnr;
|
Grow boundary layer over edges.
|
||||||
GenerateBoundaryLayer (self, blp);
|
|
||||||
}
|
)delimiter")
|
||||||
))
|
|
||||||
|
|
||||||
.def ("EnableTable", [] (Mesh & self, string name, bool set)
|
.def ("EnableTable", [] (Mesh & self, string name, bool set)
|
||||||
{
|
{
|
||||||
|
@ -166,7 +166,7 @@ public:
|
|||||||
{ return vert2element[vnr]; }
|
{ return vert2element[vnr]; }
|
||||||
|
|
||||||
void GetVertexSurfaceElements( int vnr, NgArray<SurfaceElementIndex>& elements ) const;
|
void GetVertexSurfaceElements( int vnr, NgArray<SurfaceElementIndex>& elements ) const;
|
||||||
NgFlatArray<SurfaceElementIndex> GetVertexSurfaceElements (int vnr) const
|
NgFlatArray<SurfaceElementIndex> GetVertexSurfaceElements(PointIndex vnr) const
|
||||||
{ return vert2surfelement[vnr]; }
|
{ return vert2surfelement[vnr]; }
|
||||||
|
|
||||||
NgFlatArray<SegmentIndex> GetVertexSegments (int vnr) const
|
NgFlatArray<SegmentIndex> GetVertexSegments (int vnr) const
|
||||||
|
17
ng/ngpkg.cpp
17
ng/ngpkg.cpp
@ -1155,7 +1155,7 @@ namespace netgen
|
|||||||
|
|
||||||
// Use an array to support creation of boundary
|
// Use an array to support creation of boundary
|
||||||
// layers for multiple surfaces in the future...
|
// layers for multiple surfaces in the future...
|
||||||
NgArray<int> surfid;
|
Array<int> surfid;
|
||||||
int surfinp = 0;
|
int surfinp = 0;
|
||||||
int prismlayers = 1;
|
int prismlayers = 1;
|
||||||
double hfirst = 0.01;
|
double hfirst = 0.01;
|
||||||
@ -1172,8 +1172,8 @@ namespace netgen
|
|||||||
cout << "Number of surfaces entered = " << surfid.Size() << endl;
|
cout << "Number of surfaces entered = " << surfid.Size() << endl;
|
||||||
cout << "Selected surfaces are:" << endl;
|
cout << "Selected surfaces are:" << endl;
|
||||||
|
|
||||||
for(int i = 1; i <= surfid.Size(); i++)
|
for(auto i : Range(surfid))
|
||||||
cout << "Surface " << i << ": " << surfid.Elem(i) << endl;
|
cout << "Surface " << i << ": " << surfid[i] << endl;
|
||||||
|
|
||||||
cout << endl << "Enter number of prism layers: ";
|
cout << endl << "Enter number of prism layers: ";
|
||||||
cin >> prismlayers;
|
cin >> prismlayers;
|
||||||
@ -1189,9 +1189,14 @@ namespace netgen
|
|||||||
|
|
||||||
BoundaryLayerParameters blp;
|
BoundaryLayerParameters blp;
|
||||||
blp.surfid = surfid;
|
blp.surfid = surfid;
|
||||||
blp.prismlayers = prismlayers;
|
for(auto i : Range(prismlayers))
|
||||||
blp.hfirst = blp.hfirst;
|
{
|
||||||
blp.growthfactor = growthfactor;
|
auto layer = i+1;
|
||||||
|
if(growthfactor == 1)
|
||||||
|
blp.heights.Append(layer * hfirst);
|
||||||
|
else
|
||||||
|
blp.heights.Append(hfirst * (pow(growthfactor, (layer+1))-1)/(growthfactor-1));
|
||||||
|
}
|
||||||
GenerateBoundaryLayer (*mesh, blp);
|
GenerateBoundaryLayer (*mesh, blp);
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
31
tests/pytest/test_boundarylayer.py
Normal file
31
tests/pytest/test_boundarylayer.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
import pytest
|
||||||
|
from netgen.csg import *
|
||||||
|
|
||||||
|
def GetNSurfaceElements(mesh, boundary):
|
||||||
|
nse_in_layer = 0
|
||||||
|
for el in mesh.Elements2D():
|
||||||
|
print(el.index)
|
||||||
|
if mesh.GetBCName(el.index-1) == boundary:
|
||||||
|
nse_in_layer += 1
|
||||||
|
return nse_in_layer
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("outside", [True, False])
|
||||||
|
def test_boundarylayer(outside, capfd):
|
||||||
|
mesh = unit_cube.GenerateMesh(maxh=0.3)
|
||||||
|
ne_before = mesh.ne
|
||||||
|
layer_surfacenames = ["right", "top"]
|
||||||
|
mesh.BoundaryLayer("|".join(layer_surfacenames), [0.01, 0.02], "layer", outside=outside, grow_edges=True)
|
||||||
|
|
||||||
|
should_ne = ne_before + 2 * sum([GetNSurfaceElements(mesh, surf) for surf in layer_surfacenames])
|
||||||
|
assert mesh.ne == should_ne
|
||||||
|
capture = capfd.readouterr()
|
||||||
|
assert not "elements are not matching" in capture.out
|
||||||
|
|
||||||
|
for side in ["front"]:
|
||||||
|
mesh.BoundaryLayer(side, [0.001], "layer", outside=outside, grow_edges=True)
|
||||||
|
should_ne += GetNSurfaceElements(mesh, side)
|
||||||
|
assert mesh.ne == should_ne
|
||||||
|
capture = capfd.readouterr()
|
||||||
|
assert not "elements are not matching" in capture.out
|
||||||
|
|
Loading…
Reference in New Issue
Block a user