add project to boundary in boundarylayer and correctly treat inverse boundaries

This commit is contained in:
Christopher Lackner 2020-11-03 12:28:13 +01:00
parent b855b419da
commit 9578e4a41d
4 changed files with 79 additions and 22 deletions

View File

@ -215,6 +215,11 @@ namespace netgen
if (blp.surfid.Contains(sel.GetIndex())) if (blp.surfid.Contains(sel.GetIndex()))
{ {
auto n2 = GetSurfaceNormal(mesh,sel); auto n2 = GetSurfaceNormal(mesh,sel);
auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());
auto domin = fd.DomainIn();
auto domout = fd.DomainOut();
if(blp.domains.Test(domout) && !blp.domains.Test(domin))
n2 *= -1;
if(!blp.outside) if(!blp.outside)
n2 *= -1; n2 *= -1;
for(auto pi : sel.PNums()) for(auto pi : sel.PNums())
@ -238,24 +243,37 @@ namespace netgen
} }
// project growthvector on surface for inner angles // project growthvector on surface for inner angles
// for(const auto& sel : mesh.SurfaceElements()) for(const auto& sel : mesh.SurfaceElements())
// if(!blp.surfid.Contains(sel.GetIndex())) // if(!blp.surfid.Contains(sel.GetIndex()))
// { // {
// auto n = GetSurfaceNormal(mesh, sel); if(blp.project_boundaries.Contains(sel.GetIndex()))
// for(auto pi : sel.PNums()) {
// { auto n = GetSurfaceNormal(mesh, sel);
// if(growthvectors[pi].Length2() == 0.) for(auto i : Range(sel.PNums()))
// continue; {
// auto& g = growthvectors[pi]; auto pi = sel.PNums()[i];
// auto ng = n * g; if(growthvectors[pi].Length2() == 0.)
// auto gg = g * g; continue;
// auto nn = n * n; auto next = sel.PNums()[(i+1)%sel.GetNV()];
// if(fabs(ng*ng-nn*gg) < 1e-12 || fabs(ng) < 1e-12) continue; auto prev = sel.PNums()[i == 0 ? sel.GetNV()-1 : i-1];
// auto a = -ng*ng/(ng*ng-nn * gg); auto v1 = (mesh[next] - mesh[pi]).Normalize();
// auto b = ng*gg/(ng*ng-nn*gg); auto v2 = (mesh[prev] - mesh[pi]).Normalize();
// g += a*g + b*n; auto v3 = growthvectors[pi];
// } v3.Normalize();
// } // only project if sel goes in boundarylayer direction
if((v1 * v3 < 1e-12) || (v2 * v3 < 1e-12))
continue;
auto& g = growthvectors[pi];
auto ng = n * g;
auto gg = g * g;
auto nn = n * n;
if(fabs(ng*ng-nn*gg) < 1e-12 || fabs(ng) < 1e-12) continue;
auto a = -ng*ng/(ng*ng-nn * gg);
auto b = ng*gg/(ng*ng-nn*gg);
g += a*g + b*n;
}
}
if (!blp.grow_edges) if (!blp.grow_edges)
{ {

View File

@ -18,6 +18,7 @@ public:
BitArray domains; BitArray domains;
bool outside = false; // set the boundary layer on the outside bool outside = false; // set the boundary layer on the outside
bool grow_edges = false; bool grow_edges = false;
Array<size_t> project_boundaries;
}; };
DLL_HEADER void GenerateBoundaryLayer (Mesh & mesh, DLL_HEADER void GenerateBoundaryLayer (Mesh & mesh,

View File

@ -833,6 +833,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
.def("FaceDescriptor", static_cast<FaceDescriptor&(Mesh::*)(int)> (&Mesh::GetFaceDescriptor), .def("FaceDescriptor", static_cast<FaceDescriptor&(Mesh::*)(int)> (&Mesh::GetFaceDescriptor),
py::return_value_policy::reference) py::return_value_policy::reference)
.def("GetNFaceDescriptors", &Mesh::GetNFD) .def("GetNFaceDescriptors", &Mesh::GetNFD)
.def("GetNDomains", &Mesh::GetNDomains)
.def("GetVolumeNeighboursOfSurfaceElement", [](Mesh & self, size_t sel) .def("GetVolumeNeighboursOfSurfaceElement", [](Mesh & self, size_t sel)
{ {
@ -1012,7 +1013,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
variant<double, py::list> thickness, variant<double, py::list> thickness,
variant<string, py::list> material, variant<string, py::list> material,
variant<string, int> domain, bool outside, variant<string, int> domain, bool outside,
bool grow_edges) bool grow_edges,
optional<string> project_boundaries)
{ {
BoundaryLayerParameters blp; BoundaryLayerParameters blp;
if(int* bc = get_if<int>(&boundary); bc) if(int* bc = get_if<int>(&boundary); bc)
@ -1034,7 +1036,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
if(dom_pattern) if(dom_pattern)
{ {
regex pattern(*dom_pattern); regex pattern(*dom_pattern);
if(regex_match(self.GetMaterial(fd.DomainIn()), pattern) || (fd.DomainOut() > 0 ? regex_match(self.GetMaterial(fd.DomainOut()), pattern) : false)) if((fd.DomainIn() > 0 && regex_match(self.GetMaterial(fd.DomainIn()), pattern)) || (fd.DomainOut() > 0 && regex_match(self.GetMaterial(fd.DomainOut()), pattern)))
blp.surfid.Append(i); blp.surfid.Append(i);
} }
else else
@ -1043,6 +1045,14 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
} }
} }
if(project_boundaries.has_value())
{
regex pattern(*project_boundaries);
for(int i = 1; i<=self.GetNFD(); i++)
if(regex_match(self.GetFaceDescriptor(i).GetBCName(), pattern))
blp.project_boundaries.Append(i);
}
if(double* pthickness = get_if<double>(&thickness); pthickness) if(double* pthickness = get_if<double>(&thickness); pthickness)
{ {
blp.heights.Append(*pthickness); blp.heights.Append(*pthickness);
@ -1102,7 +1112,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
self.UpdateTopology(); self.UpdateTopology();
}, py::arg("boundary"), py::arg("thickness"), py::arg("material"), }, py::arg("boundary"), py::arg("thickness"), py::arg("material"),
py::arg("domains") = ".*", py::arg("outside") = false, py::arg("domains") = ".*", py::arg("outside") = false,
py::arg("grow_edges") = false, py::arg("grow_edges") = false, py::arg("project_boundaries")=nullopt,
R"delimiter( R"delimiter(
Add boundary layer to mesh. Add boundary layer to mesh.
@ -1127,6 +1137,11 @@ outside : bool = False
grow_edges : bool = False grow_edges : bool = False
Grow boundary layer over edges. Grow boundary layer over edges.
project_boundaries : Optional[str] = None
Project boundarylayer to these boundaries if they meet them. Set
to boundaries that meet boundarylayer at a non-orthogonal edge and
layer-ending should be projected to that boundary.
)delimiter") )delimiter")
.def ("EnableTable", [] (Mesh & self, string name, bool set) .def ("EnableTable", [] (Mesh & self, string name, bool set)

View File

@ -54,6 +54,29 @@ def test_boundarylayer2(outside, version, capfd):
mesh = geo.GenerateMesh() mesh = geo.GenerateMesh()
should_ne = mesh.ne + 2 * GetNSurfaceElements(mesh, ["default"], "part") should_ne = mesh.ne + 2 * GetNSurfaceElements(mesh, ["default"], "part")
layersize = 0.05 layersize = 0.05
mesh.BoundaryLayer("default", [0.5 * layersize, layersize], "layer", domains="part", outside=outside, grow_edges=True) mesh.BoundaryLayer("default", [0.5 * layersize, layersize], "part", domains="part", outside=outside, grow_edges=True)
assert mesh.ne == should_ne assert mesh.ne == should_ne
assert not "elements are not matching" in capfd.readouterr().out assert not "elements are not matching" in capfd.readouterr().out
import netgen.gui
ngs = pytest.importorskip("ngsolve")
ngs.Draw(ngs.Mesh(mesh))
mesh = ngs.Mesh(mesh)
assert ngs.Integrate(1, mesh.Materials("part")) == pytest.approx(0.5*2.05*2.05 if outside else 0.4*2*2)
assert ngs.Integrate(1, mesh) == pytest.approx(3**3)
@pytest.mark.parametrize("outside", [True, False])
def test_wrong_orientation(outside):
geo = CSGeometry()
brick = OrthoBrick((-1,0,0),(1,1,1)) - Plane((0,0,0), (1,0,0))
geo.Add(brick.mat("air"))
mesh = geo.GenerateMesh()
mesh.BoundaryLayer(".*", 0.1, "air", domains="air", outside=outside,
grow_edges=True)
ngs = pytest.importorskip("ngsolve")
mesh = ngs.Mesh(mesh)
assert ngs.Integrate(1, mesh) == pytest.approx(1.2**3 if outside else 1)