mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-15 02:18:33 +05:00
formatting
This commit is contained in:
parent
e5af7bca42
commit
82965f63b0
64
.clang-format
Normal file
64
.clang-format
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: true
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: true
|
||||||
|
BeforeCatch: true
|
||||||
|
BeforeElse: true
|
||||||
|
IndentBraces: true
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakInheritanceList: AfterColon
|
||||||
|
ColumnLimit: 0
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 2
|
||||||
|
ContinuationIndentWidth: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
EmptyLineBeforeAccessModifier: Never
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceBeforeParens: Custom
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterFunctionDefinitionName: true
|
||||||
|
AfterFunctionDeclarationName: true
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Latest
|
||||||
|
TabWidth: 2
|
||||||
|
UseTab: Never
|
||||||
|
|
@ -8,22 +8,28 @@
|
|||||||
#include "global.hpp"
|
#include "global.hpp"
|
||||||
#include "meshfunc.hpp"
|
#include "meshfunc.hpp"
|
||||||
|
|
||||||
namespace netgen {
|
namespace netgen
|
||||||
|
{
|
||||||
|
|
||||||
struct SpecialPointException : public Exception {
|
struct SpecialPointException : public Exception
|
||||||
SpecialPointException() : Exception("") {}
|
{
|
||||||
|
SpecialPointException()
|
||||||
|
: Exception("") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::tuple<int, int> FindCloseVectors (FlatArray<Vec<3>> ns,
|
std::tuple<int, int> FindCloseVectors (FlatArray<Vec<3>> ns,
|
||||||
bool find_max = true) {
|
bool find_max = true)
|
||||||
|
{
|
||||||
int maxpos1;
|
int maxpos1;
|
||||||
int maxpos2;
|
int maxpos2;
|
||||||
|
|
||||||
double val = find_max ? -1e99 : 1e99;
|
double val = find_max ? -1e99 : 1e99;
|
||||||
for (auto i : Range(ns))
|
for (auto i : Range(ns))
|
||||||
for (auto j : Range(i + 1, ns.Size())) {
|
for (auto j : Range(i + 1, ns.Size()))
|
||||||
|
{
|
||||||
double ip = ns[i] * ns[j];
|
double ip = ns[i] * ns[j];
|
||||||
if ((find_max && (ip > val)) || (!find_max && (ip < val))) {
|
if ((find_max && (ip > val)) || (!find_max && (ip < val)))
|
||||||
|
{
|
||||||
val = ip;
|
val = ip;
|
||||||
maxpos1 = i;
|
maxpos1 = i;
|
||||||
maxpos2 = j;
|
maxpos2 = j;
|
||||||
@ -32,12 +38,14 @@ std::tuple<int, int> FindCloseVectors(FlatArray<Vec<3>> ns,
|
|||||||
return {maxpos1, maxpos2};
|
return {maxpos1, maxpos2};
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec<3> CalcGrowthVector(FlatArray<Vec<3>> ns) {
|
Vec<3> CalcGrowthVector (FlatArray<Vec<3>> ns)
|
||||||
|
{
|
||||||
if (ns.Size() == 0)
|
if (ns.Size() == 0)
|
||||||
return {0, 0, 0};
|
return {0, 0, 0};
|
||||||
if (ns.Size() == 1)
|
if (ns.Size() == 1)
|
||||||
return ns[0];
|
return ns[0];
|
||||||
if (ns.Size() == 2) {
|
if (ns.Size() == 2)
|
||||||
|
{
|
||||||
auto gw = ns[0];
|
auto gw = ns[0];
|
||||||
auto n = ns[1];
|
auto n = ns[1];
|
||||||
auto npn = gw * n;
|
auto npn = gw * n;
|
||||||
@ -48,13 +56,15 @@ Vec<3> CalcGrowthVector(FlatArray<Vec<3>> ns) {
|
|||||||
gw += (nn - npn) / (nn - npn * npn / npnp) * (n - npn / npnp * gw);
|
gw += (nn - npn) / (nn - npn * npn / npnp) * (n - npn / npnp * gw);
|
||||||
return gw;
|
return gw;
|
||||||
}
|
}
|
||||||
if (ns.Size() == 3) {
|
if (ns.Size() == 3)
|
||||||
|
{
|
||||||
DenseMatrix mat(3, 3);
|
DenseMatrix mat(3, 3);
|
||||||
for (auto i : Range(3))
|
for (auto i : Range(3))
|
||||||
for (auto j : Range(3))
|
for (auto j : Range(3))
|
||||||
mat(i, j) = ns[i][j];
|
mat(i, j) = ns[i][j];
|
||||||
|
|
||||||
if (fabs(mat.Det()) > 1e-6) {
|
if (fabs(mat.Det()) > 1e-6)
|
||||||
|
{
|
||||||
DenseMatrix mat(3, 3);
|
DenseMatrix mat(3, 3);
|
||||||
for (auto i : Range(3))
|
for (auto i : Range(3))
|
||||||
for (auto j : Range(3))
|
for (auto j : Range(3))
|
||||||
@ -88,17 +98,20 @@ Vec<3> CalcGrowthVector(FlatArray<Vec<3>> ns) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SpecialBoundaryPoint ::GrowthGroup ::GrowthGroup(FlatArray<int> faces_,
|
SpecialBoundaryPoint ::GrowthGroup ::GrowthGroup(FlatArray<int> faces_,
|
||||||
FlatArray<Vec<3>> normals) {
|
FlatArray<Vec<3>> normals)
|
||||||
|
{
|
||||||
faces = faces_;
|
faces = faces_;
|
||||||
growth_vector = CalcGrowthVector(normals);
|
growth_vector = CalcGrowthVector(normals);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpecialBoundaryPoint ::SpecialBoundaryPoint(
|
SpecialBoundaryPoint ::SpecialBoundaryPoint(
|
||||||
const std::map<int, Vec<3>> &normals) {
|
const std::map<int, Vec<3>>& normals)
|
||||||
|
{
|
||||||
// find opposing face normals
|
// find opposing face normals
|
||||||
Array<Vec<3>> ns;
|
Array<Vec<3>> ns;
|
||||||
Array<int> faces;
|
Array<int> faces;
|
||||||
for (auto [face, normal] : normals) {
|
for (auto [face, normal] : normals)
|
||||||
|
{
|
||||||
ns.Append(normal);
|
ns.Append(normal);
|
||||||
faces.Append(face);
|
faces.Append(face);
|
||||||
}
|
}
|
||||||
@ -116,7 +129,8 @@ SpecialBoundaryPoint ::SpecialBoundaryPoint(
|
|||||||
|
|
||||||
Array<Vec<3>> normals1, normals2;
|
Array<Vec<3>> normals1, normals2;
|
||||||
for (auto [facei, normali] : normals)
|
for (auto [facei, normali] : normals)
|
||||||
if (facei != minface1 && facei != minface2) {
|
if (facei != minface1 && facei != minface2)
|
||||||
|
{
|
||||||
g1_faces.Append(facei);
|
g1_faces.Append(facei);
|
||||||
g2_faces.Append(facei);
|
g2_faces.Append(facei);
|
||||||
}
|
}
|
||||||
@ -128,11 +142,12 @@ SpecialBoundaryPoint ::SpecialBoundaryPoint(
|
|||||||
growth_groups.Append(GrowthGroup(g2_faces, normals2));
|
growth_groups.Append(GrowthGroup(g2_faces, normals2));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec<3> BoundaryLayerTool ::getEdgeTangent(PointIndex pi, int edgenr,
|
Vec<3> BoundaryLayerTool ::getEdgeTangent(PointIndex pi, int edgenr, FlatArray<Segment*> segs)
|
||||||
FlatArray<Segment *> segs) {
|
{
|
||||||
Vec<3> tangent = 0.0;
|
Vec<3> tangent = 0.0;
|
||||||
ArrayMem<PointIndex, 2> pts;
|
ArrayMem<PointIndex, 2> pts;
|
||||||
for (auto *p_seg : segs) {
|
for (auto* p_seg : segs)
|
||||||
|
{
|
||||||
auto& seg = *p_seg;
|
auto& seg = *p_seg;
|
||||||
if (seg.edgenr != edgenr)
|
if (seg.edgenr != edgenr)
|
||||||
continue;
|
continue;
|
||||||
@ -140,7 +155,8 @@ Vec<3> BoundaryLayerTool ::getEdgeTangent(PointIndex pi, int edgenr,
|
|||||||
if (!pts.Contains(other))
|
if (!pts.Contains(other))
|
||||||
pts.Append(other);
|
pts.Append(other);
|
||||||
}
|
}
|
||||||
if (pts.Size() != 2) {
|
if (pts.Size() != 2)
|
||||||
|
{
|
||||||
cout << "getEdgeTangent pi = " << pi << ", edgenr = " << edgenr << endl;
|
cout << "getEdgeTangent pi = " << pi << ", edgenr = " << edgenr << endl;
|
||||||
cout << pts << endl;
|
cout << pts << endl;
|
||||||
for (auto* p_seg : segs)
|
for (auto* p_seg : segs)
|
||||||
@ -151,7 +167,8 @@ Vec<3> BoundaryLayerTool ::getEdgeTangent(PointIndex pi, int edgenr,
|
|||||||
return tangent.Normalize();
|
return tangent.Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::LimitGrowthVectorLengths() {
|
void BoundaryLayerTool ::LimitGrowthVectorLengths()
|
||||||
|
{
|
||||||
static Timer tall("BoundaryLayerTool::LimitGrowthVectorLengths");
|
static Timer tall("BoundaryLayerTool::LimitGrowthVectorLengths");
|
||||||
RegionTimer rtall(tall);
|
RegionTimer rtall(tall);
|
||||||
|
|
||||||
@ -161,11 +178,13 @@ void BoundaryLayerTool ::LimitGrowthVectorLengths() {
|
|||||||
|
|
||||||
// depending on the geometry type, the mesh contains segments multiple times
|
// depending on the geometry type, the mesh contains segments multiple times
|
||||||
// (once for each face)
|
// (once for each face)
|
||||||
bool HaveSingleSegments(const Mesh &mesh) {
|
bool HaveSingleSegments (const Mesh& mesh)
|
||||||
|
{
|
||||||
auto& topo = mesh.GetTopology();
|
auto& topo = mesh.GetTopology();
|
||||||
NgArray<SurfaceElementIndex> surf_els;
|
NgArray<SurfaceElementIndex> surf_els;
|
||||||
|
|
||||||
for (auto segi : Range(mesh.LineSegments())) {
|
for (auto segi : Range(mesh.LineSegments()))
|
||||||
|
{
|
||||||
mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);
|
mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);
|
||||||
if (surf_els.Size() < 2)
|
if (surf_els.Size() < 2)
|
||||||
continue;
|
continue;
|
||||||
@ -175,7 +194,8 @@ bool HaveSingleSegments(const Mesh &mesh) {
|
|||||||
auto pi1 = max(seg[0], seg[1]);
|
auto pi1 = max(seg[0], seg[1]);
|
||||||
auto p0_segs = topo.GetVertexSegments(seg[0]);
|
auto p0_segs = topo.GetVertexSegments(seg[0]);
|
||||||
|
|
||||||
for (auto segi_other : p0_segs) {
|
for (auto segi_other : p0_segs)
|
||||||
|
{
|
||||||
if (segi_other == segi)
|
if (segi_other == segi)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -196,22 +216,27 @@ bool HaveSingleSegments(const Mesh &mesh) {
|
|||||||
|
|
||||||
// duplicates segments (and sets seg.si accordingly) to have a unified data
|
// duplicates segments (and sets seg.si accordingly) to have a unified data
|
||||||
// structure for all geometry types
|
// structure for all geometry types
|
||||||
Array<Segment> BuildSegments(Mesh &mesh) {
|
Array<Segment> BuildSegments (Mesh& mesh)
|
||||||
|
{
|
||||||
Array<Segment> segments;
|
Array<Segment> segments;
|
||||||
// auto& topo = mesh.GetTopology();
|
// auto& topo = mesh.GetTopology();
|
||||||
|
|
||||||
NgArray<SurfaceElementIndex> surf_els;
|
NgArray<SurfaceElementIndex> surf_els;
|
||||||
|
|
||||||
for (auto segi : Range(mesh.LineSegments())) {
|
for (auto segi : Range(mesh.LineSegments()))
|
||||||
|
{
|
||||||
auto seg = mesh[segi];
|
auto seg = mesh[segi];
|
||||||
mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);
|
mesh.GetTopology().GetSegmentSurfaceElements(segi + 1, surf_els);
|
||||||
for (auto seli : surf_els) {
|
for (auto seli : surf_els)
|
||||||
|
{
|
||||||
const auto& sel = mesh[seli];
|
const auto& sel = mesh[seli];
|
||||||
seg.si = sel.GetIndex();
|
seg.si = sel.GetIndex();
|
||||||
|
|
||||||
auto np = sel.GetNP();
|
auto np = sel.GetNP();
|
||||||
for (auto i : Range(np)) {
|
for (auto i : Range(np))
|
||||||
if (sel[i] == seg[0]) {
|
{
|
||||||
|
if (sel[i] == seg[0])
|
||||||
|
{
|
||||||
if (sel[(i + 1) % np] != seg[1])
|
if (sel[(i + 1) % np] != seg[1])
|
||||||
swap(seg[0], seg[1]);
|
swap(seg[0], seg[1]);
|
||||||
break;
|
break;
|
||||||
@ -224,17 +249,17 @@ Array<Segment> BuildSegments(Mesh &mesh) {
|
|||||||
return segments;
|
return segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergeAndAddSegments(Mesh &mesh, FlatArray<Segment> segments,
|
void MergeAndAddSegments (Mesh& mesh, FlatArray<Segment> segments, FlatArray<Segment> new_segments)
|
||||||
FlatArray<Segment> new_segments) {
|
{
|
||||||
INDEX_2_HASHTABLE<bool> already_added(segments.Size() +
|
INDEX_2_HASHTABLE<bool> already_added(segments.Size() + 2 * new_segments.Size());
|
||||||
2 * new_segments.Size());
|
|
||||||
|
|
||||||
mesh.LineSegments().SetSize0();
|
mesh.LineSegments().SetSize0();
|
||||||
|
|
||||||
auto addSegment = [&] (const auto& seg) {
|
auto addSegment = [&] (const auto& seg) {
|
||||||
INDEX_2 i2(seg[0], seg[1]);
|
INDEX_2 i2(seg[0], seg[1]);
|
||||||
i2.Sort();
|
i2.Sort();
|
||||||
if (!already_added.Used(i2)) {
|
if (!already_added.Used(i2))
|
||||||
|
{
|
||||||
mesh.AddSegment(seg);
|
mesh.AddSegment(seg);
|
||||||
already_added.Set(i2, true);
|
already_added.Set(i2, true);
|
||||||
}
|
}
|
||||||
@ -249,7 +274,8 @@ void MergeAndAddSegments(Mesh &mesh, FlatArray<Segment> segments,
|
|||||||
|
|
||||||
BoundaryLayerTool::BoundaryLayerTool(Mesh& mesh_,
|
BoundaryLayerTool::BoundaryLayerTool(Mesh& mesh_,
|
||||||
const BoundaryLayerParameters& params_)
|
const BoundaryLayerParameters& params_)
|
||||||
: mesh(mesh_), topo(mesh_.GetTopology()), params(params_) {
|
: mesh(mesh_), topo(mesh_.GetTopology()), params(params_)
|
||||||
|
{
|
||||||
static Timer timer("BoundaryLayerTool::ctor");
|
static Timer timer("BoundaryLayerTool::ctor");
|
||||||
RegionTimer regt(timer);
|
RegionTimer regt(timer);
|
||||||
ProcessParameters();
|
ProcessParameters();
|
||||||
@ -281,23 +307,27 @@ BoundaryLayerTool::BoundaryLayerTool(Mesh &mesh_,
|
|||||||
si_map[i] = i;
|
si_map[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::CreateNewFaceDescriptors() {
|
void BoundaryLayerTool ::CreateNewFaceDescriptors()
|
||||||
|
{
|
||||||
surfacefacs.SetSize(nfd_old + 1);
|
surfacefacs.SetSize(nfd_old + 1);
|
||||||
surfacefacs = 0.0;
|
surfacefacs = 0.0;
|
||||||
// create new FaceDescriptors
|
// create new FaceDescriptors
|
||||||
for (auto i : Range(1, nfd_old + 1)) {
|
for (auto i : Range(1, nfd_old + 1))
|
||||||
|
{
|
||||||
const auto& fd = mesh.GetFaceDescriptor(i);
|
const auto& fd = mesh.GetFaceDescriptor(i);
|
||||||
string name = fd.GetBCName();
|
string name = fd.GetBCName();
|
||||||
if (par_surfid.Contains(i)) {
|
if (par_surfid.Contains(i))
|
||||||
|
{
|
||||||
if (auto isIn = domains.Test(fd.DomainIn());
|
if (auto isIn = domains.Test(fd.DomainIn());
|
||||||
isIn != domains.Test(fd.DomainOut())) {
|
isIn != domains.Test(fd.DomainOut()))
|
||||||
|
{
|
||||||
int new_si = mesh.GetNFD() + 1;
|
int new_si = mesh.GetNFD() + 1;
|
||||||
surfacefacs[i] = isIn ? 1. : -1.;
|
surfacefacs[i] = isIn ? 1. : -1.;
|
||||||
moved_surfaces.SetBit(i);
|
moved_surfaces.SetBit(i);
|
||||||
if (!insert_only_volume_elements) {
|
if (!insert_only_volume_elements)
|
||||||
|
{
|
||||||
// -1 surf nr is so that curving does not do anything
|
// -1 surf nr is so that curving does not do anything
|
||||||
FaceDescriptor new_fd(-1, isIn ? new_mat_nrs[i] : fd.DomainIn(),
|
FaceDescriptor new_fd(-1, isIn ? new_mat_nrs[i] : fd.DomainIn(), isIn ? fd.DomainOut() : new_mat_nrs[i], -1);
|
||||||
isIn ? fd.DomainOut() : new_mat_nrs[i], -1);
|
|
||||||
new_fd.SetBCProperty(new_si);
|
new_fd.SetBCProperty(new_si);
|
||||||
new_fd.SetSurfColour(fd.SurfColour());
|
new_fd.SetSurfColour(fd.SurfColour());
|
||||||
mesh.AddFaceDescriptor(new_fd);
|
mesh.AddFaceDescriptor(new_fd);
|
||||||
@ -316,22 +346,24 @@ void BoundaryLayerTool ::CreateNewFaceDescriptors() {
|
|||||||
|
|
||||||
for (auto si : par_surfid)
|
for (auto si : par_surfid)
|
||||||
if (surfacefacs[si] == 0.0)
|
if (surfacefacs[si] == 0.0)
|
||||||
throw Exception("Surface " + to_string(si) +
|
throw Exception("Surface " + to_string(si) + " is not a boundary of the domain to be grown into!");
|
||||||
" is not a boundary of the domain to be grown into!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::CreateFaceDescriptorsSides() {
|
void BoundaryLayerTool ::CreateFaceDescriptorsSides()
|
||||||
|
{
|
||||||
if (insert_only_volume_elements)
|
if (insert_only_volume_elements)
|
||||||
return;
|
return;
|
||||||
BitArray face_done(mesh.GetNFD() + 1);
|
BitArray face_done(mesh.GetNFD() + 1);
|
||||||
face_done.Clear();
|
face_done.Clear();
|
||||||
for (const auto &sel : mesh.SurfaceElements()) {
|
for (const auto& sel : mesh.SurfaceElements())
|
||||||
|
{
|
||||||
auto facei = sel.GetIndex();
|
auto facei = sel.GetIndex();
|
||||||
if (face_done.Test(facei))
|
if (face_done.Test(facei))
|
||||||
continue;
|
continue;
|
||||||
bool point_moved = false;
|
bool point_moved = false;
|
||||||
// bool point_fixed = false;
|
// bool point_fixed = false;
|
||||||
for (auto pi : sel.PNums()) {
|
for (auto pi : sel.PNums())
|
||||||
|
{
|
||||||
if (growthvectors[pi].Length() > 0)
|
if (growthvectors[pi].Length() > 0)
|
||||||
point_moved = true;
|
point_moved = true;
|
||||||
/*
|
/*
|
||||||
@ -339,7 +371,8 @@ void BoundaryLayerTool ::CreateFaceDescriptorsSides() {
|
|||||||
point_fixed = true;
|
point_fixed = true;
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (point_moved && !moved_surfaces.Test(facei)) {
|
if (point_moved && !moved_surfaces.Test(facei))
|
||||||
|
{
|
||||||
int new_si = mesh.GetNFD() + 1;
|
int new_si = mesh.GetNFD() + 1;
|
||||||
const auto& fd = mesh.GetFaceDescriptor(facei);
|
const auto& fd = mesh.GetFaceDescriptor(facei);
|
||||||
// auto isIn = domains.Test(fd.DomainIn());
|
// auto isIn = domains.Test(fd.DomainIn());
|
||||||
@ -356,11 +389,13 @@ void BoundaryLayerTool ::CreateFaceDescriptorsSides() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::CalculateGrowthVectors() {
|
void BoundaryLayerTool ::CalculateGrowthVectors()
|
||||||
|
{
|
||||||
growthvectors.SetSize(np);
|
growthvectors.SetSize(np);
|
||||||
growthvectors = 0.;
|
growthvectors = 0.;
|
||||||
|
|
||||||
for (auto pi : mesh.Points().Range()) {
|
for (auto pi : mesh.Points().Range())
|
||||||
|
{
|
||||||
const auto& p = mesh[pi];
|
const auto& p = mesh[pi];
|
||||||
if (p.Type() == INNERPOINT)
|
if (p.Type() == INNERPOINT)
|
||||||
continue;
|
continue;
|
||||||
@ -369,7 +404,8 @@ void BoundaryLayerTool ::CalculateGrowthVectors() {
|
|||||||
|
|
||||||
// calculate one normal vector per face (average with angles as weights for
|
// calculate one normal vector per face (average with angles as weights for
|
||||||
// multiple surface elements within a face)
|
// multiple surface elements within a face)
|
||||||
for (auto sei : p2sel[pi]) {
|
for (auto sei : p2sel[pi])
|
||||||
|
{
|
||||||
const auto& sel = mesh[sei];
|
const auto& sel = mesh[sei];
|
||||||
auto facei = sel.GetIndex();
|
auto facei = sel.GetIndex();
|
||||||
if (!par_surfid.Contains(facei))
|
if (!par_surfid.Contains(facei))
|
||||||
@ -391,13 +427,17 @@ void BoundaryLayerTool ::CalculateGrowthVectors() {
|
|||||||
|
|
||||||
// combine normal vectors for each face to keep uniform distances
|
// combine normal vectors for each face to keep uniform distances
|
||||||
ArrayMem<Vec<3>, 5> ns;
|
ArrayMem<Vec<3>, 5> ns;
|
||||||
for (auto &[facei, n] : normals) {
|
for (auto& [facei, n] : normals)
|
||||||
|
{
|
||||||
ns.Append(n);
|
ns.Append(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
growthvectors[pi] = CalcGrowthVector(ns);
|
growthvectors[pi] = CalcGrowthVector(ns);
|
||||||
} catch (const SpecialPointException &e) {
|
}
|
||||||
|
catch (const SpecialPointException& e)
|
||||||
|
{
|
||||||
special_boundary_points.emplace(pi, normals);
|
special_boundary_points.emplace(pi, normals);
|
||||||
growthvectors[pi] =
|
growthvectors[pi] =
|
||||||
special_boundary_points[pi].growth_groups[0].growth_vector;
|
special_boundary_points[pi].growth_groups[0].growth_vector;
|
||||||
@ -406,7 +446,8 @@ void BoundaryLayerTool ::CalculateGrowthVectors() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Array<Array<pair<SegmentIndex, int>>, SegmentIndex>
|
Array<Array<pair<SegmentIndex, int>>, SegmentIndex>
|
||||||
BoundaryLayerTool ::BuildSegMap() {
|
BoundaryLayerTool ::BuildSegMap()
|
||||||
|
{
|
||||||
// Bit array to keep track of segments already processed
|
// Bit array to keep track of segments already processed
|
||||||
BitArray segs_done(nseg + 1);
|
BitArray segs_done(nseg + 1);
|
||||||
segs_done.Clear();
|
segs_done.Clear();
|
||||||
@ -431,7 +472,8 @@ BoundaryLayerTool ::BuildSegMap() {
|
|||||||
is_boundary_moved.SetSize(nfd_old + 1);
|
is_boundary_moved.SetSize(nfd_old + 1);
|
||||||
is_boundary_moved.Clear();
|
is_boundary_moved.Clear();
|
||||||
|
|
||||||
for (auto si : Range(segments)) {
|
for (auto si : Range(segments))
|
||||||
|
{
|
||||||
if (segs_done[si])
|
if (segs_done[si])
|
||||||
continue;
|
continue;
|
||||||
const auto& segi = segments[si];
|
const auto& segi = segments[si];
|
||||||
@ -441,30 +483,36 @@ BoundaryLayerTool ::BuildSegMap() {
|
|||||||
segmap[si].Append(make_pair(si, 0));
|
segmap[si].Append(make_pair(si, 0));
|
||||||
moved_segs.Append(si);
|
moved_segs.Append(si);
|
||||||
is_edge_moved.SetBit(segi.edgenr);
|
is_edge_moved.SetBit(segi.edgenr);
|
||||||
for (auto sj : Range(segments)) {
|
for (auto sj : Range(segments))
|
||||||
|
{
|
||||||
if (segs_done.Test(sj))
|
if (segs_done.Test(sj))
|
||||||
continue;
|
continue;
|
||||||
const auto& segj = segments[sj];
|
const auto& segj = segments[sj];
|
||||||
if ((segi[0] == segj[0] && segi[1] == segj[1]) ||
|
if ((segi[0] == segj[0] && segi[1] == segj[1]) || (segi[0] == segj[1] && segi[1] == segj[0]))
|
||||||
(segi[0] == segj[1] && segi[1] == segj[0])) {
|
{
|
||||||
segs_done.SetBit(sj);
|
segs_done.SetBit(sj);
|
||||||
int type;
|
int type;
|
||||||
if (moved_surfaces.Test(segj.si)) {
|
if (moved_surfaces.Test(segj.si))
|
||||||
|
{
|
||||||
type = 0;
|
type = 0;
|
||||||
moved_segs.Append(sj);
|
moved_segs.Append(sj);
|
||||||
} else if (const auto &fd = mesh.GetFaceDescriptor(segj.si);
|
}
|
||||||
domains.Test(fd.DomainIn()) &&
|
else if (const auto& fd = mesh.GetFaceDescriptor(segj.si);
|
||||||
domains.Test(fd.DomainOut())) {
|
domains.Test(fd.DomainIn()) && domains.Test(fd.DomainOut()))
|
||||||
|
{
|
||||||
type = 2;
|
type = 2;
|
||||||
if (fd.DomainIn() == 0 || fd.DomainOut() == 0)
|
if (fd.DomainIn() == 0 || fd.DomainOut() == 0)
|
||||||
is_boundary_projected.SetBit(segj.si);
|
is_boundary_projected.SetBit(segj.si);
|
||||||
} else if (const auto &fd = mesh.GetFaceDescriptor(segj.si);
|
}
|
||||||
!domains.Test(fd.DomainIn()) &&
|
else if (const auto& fd = mesh.GetFaceDescriptor(segj.si);
|
||||||
!domains.Test(fd.DomainOut())) {
|
!domains.Test(fd.DomainIn()) && !domains.Test(fd.DomainOut()))
|
||||||
|
{
|
||||||
type = 3;
|
type = 3;
|
||||||
// cout << "set is_moved boundary to type 3 for " << segj.si << endl;
|
// cout << "set is_moved boundary to type 3 for " << segj.si << endl;
|
||||||
is_boundary_moved.SetBit(segj.si);
|
is_boundary_moved.SetBit(segj.si);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
type = 1;
|
type = 1;
|
||||||
// in case 1 we project the growthvector onto the surface
|
// in case 1 we project the growthvector onto the surface
|
||||||
is_boundary_projected.SetBit(segj.si);
|
is_boundary_projected.SetBit(segj.si);
|
||||||
@ -477,15 +525,19 @@ BoundaryLayerTool ::BuildSegMap() {
|
|||||||
return segmap;
|
return segmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface() {
|
BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface()
|
||||||
|
{
|
||||||
BitArray in_surface_direction(nfd_old + 1);
|
BitArray in_surface_direction(nfd_old + 1);
|
||||||
in_surface_direction.Clear();
|
in_surface_direction.Clear();
|
||||||
// project growthvector on surface for inner angles
|
// project growthvector on surface for inner angles
|
||||||
if (params.grow_edges) {
|
if (params.grow_edges)
|
||||||
|
{
|
||||||
for (const auto& sel : mesh.SurfaceElements())
|
for (const auto& sel : mesh.SurfaceElements())
|
||||||
if (is_boundary_projected.Test(sel.GetIndex())) {
|
if (is_boundary_projected.Test(sel.GetIndex()))
|
||||||
|
{
|
||||||
auto n = getNormal(sel);
|
auto n = getNormal(sel);
|
||||||
for (auto i : Range(sel.PNums())) {
|
for (auto i : Range(sel.PNums()))
|
||||||
|
{
|
||||||
auto pi = sel.PNums()[i];
|
auto pi = sel.PNums()[i];
|
||||||
if (growthvectors[pi].Length2() == 0.)
|
if (growthvectors[pi].Length2() == 0.)
|
||||||
continue;
|
continue;
|
||||||
@ -513,15 +565,17 @@ BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface() {
|
|||||||
g += a * g + b * n;
|
g += a * g + b * n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
for (const auto &seg : segments) {
|
else
|
||||||
|
{
|
||||||
|
for (const auto& seg : segments)
|
||||||
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (const auto& seg2 : segments)
|
for (const auto& seg2 : segments)
|
||||||
if (((seg[0] == seg2[0] && seg[1] == seg2[1]) ||
|
if (((seg[0] == seg2[0] && seg[1] == seg2[1]) || (seg[0] == seg2[1] && seg[1] == seg2[0])) && par_surfid.Contains(seg2.si))
|
||||||
(seg[0] == seg2[1] && seg[1] == seg2[0])) &&
|
|
||||||
par_surfid.Contains(seg2.si))
|
|
||||||
count++;
|
count++;
|
||||||
if (count == 1) {
|
if (count == 1)
|
||||||
|
{
|
||||||
growthvectors[seg[0]] = {0., 0., 0.};
|
growthvectors[seg[0]] = {0., 0., 0.};
|
||||||
growthvectors[seg[1]] = {0., 0., 0.};
|
growthvectors[seg[1]] = {0., 0., 0.};
|
||||||
}
|
}
|
||||||
@ -533,7 +587,8 @@ BitArray BoundaryLayerTool ::ProjectGrowthVectorsOnSurface() {
|
|||||||
|
|
||||||
void BoundaryLayerTool ::InsertNewElements(
|
void BoundaryLayerTool ::InsertNewElements(
|
||||||
FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap,
|
FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap,
|
||||||
const BitArray &in_surface_direction) {
|
const BitArray& in_surface_direction)
|
||||||
|
{
|
||||||
static Timer timer("BoundaryLayerTool::InsertNewElements");
|
static Timer timer("BoundaryLayerTool::InsertNewElements");
|
||||||
RegionTimer rt(timer);
|
RegionTimer rt(timer);
|
||||||
mapto.SetSize(0);
|
mapto.SetSize(0);
|
||||||
@ -548,12 +603,12 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
auto& identifications = mesh.GetIdentifications();
|
auto& identifications = mesh.GetIdentifications();
|
||||||
const int identnr = identifications.GetNr("boundarylayer");
|
const int identnr = identifications.GetNr("boundarylayer");
|
||||||
|
|
||||||
auto add_points = [&](PointIndex pi, Vec<3> &growth_vector,
|
auto add_points = [&] (PointIndex pi, Vec<3>& growth_vector, Array<PointIndex>& new_points) {
|
||||||
Array<PointIndex> &new_points) {
|
|
||||||
Point<3> p = mesh[pi];
|
Point<3> p = mesh[pi];
|
||||||
PointIndex pi_last = pi;
|
PointIndex pi_last = pi;
|
||||||
double height = 0.0;
|
double height = 0.0;
|
||||||
for (auto i : Range(par_heights)) {
|
for (auto i : Range(par_heights))
|
||||||
|
{
|
||||||
height += par_heights[i];
|
height += par_heights[i];
|
||||||
auto pi_new = mesh.AddPoint(p);
|
auto pi_new = mesh.AddPoint(p);
|
||||||
// mesh.AddLockedPoint(pi_new);
|
// mesh.AddLockedPoint(pi_new);
|
||||||
@ -567,12 +622,16 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// insert new points
|
// insert new points
|
||||||
for (PointIndex pi = 1; pi <= np; pi++) {
|
for (PointIndex pi = 1; pi <= np; pi++)
|
||||||
if (growthvectors[pi].Length2() != 0) {
|
{
|
||||||
if (special_boundary_points.count(pi)) {
|
if (growthvectors[pi].Length2() != 0)
|
||||||
|
{
|
||||||
|
if (special_boundary_points.count(pi))
|
||||||
|
{
|
||||||
for (auto& group : special_boundary_points[pi].growth_groups)
|
for (auto& group : special_boundary_points[pi].growth_groups)
|
||||||
add_points(pi, group.growth_vector, group.new_points);
|
add_points(pi, group.growth_vector, group.new_points);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
add_points(pi, growthvectors[pi], mapto[pi]);
|
add_points(pi, growthvectors[pi], mapto[pi]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,7 +661,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
auto getGroups = [&] (PointIndex pi, int face_index) -> Array<int> {
|
auto getGroups = [&] (PointIndex pi, int face_index) -> Array<int> {
|
||||||
auto n = numGroups(pi);
|
auto n = numGroups(pi);
|
||||||
Array<int> groups;
|
Array<int> groups;
|
||||||
if (n == 1) {
|
if (n == 1)
|
||||||
|
{
|
||||||
groups.Append(0);
|
groups.Append(0);
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
@ -623,16 +683,19 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
edge_map[ei] = ++edge_nr;
|
edge_map[ei] = ++edge_nr;
|
||||||
return edge_map[ei];
|
return edge_map[ei];
|
||||||
};
|
};
|
||||||
if (params.grow_edges) {
|
if (params.grow_edges)
|
||||||
for (auto sei : moved_segs) {
|
{
|
||||||
|
for (auto sei : moved_segs)
|
||||||
|
{
|
||||||
// copy here since we will add segments and this would
|
// copy here since we will add segments and this would
|
||||||
// invalidate a reference!
|
// invalidate a reference!
|
||||||
// auto segi = segments[sei];
|
// auto segi = segments[sei];
|
||||||
for (auto [sej, type] : segmap[sei]) {
|
for (auto [sej, type] : segmap[sei])
|
||||||
|
{
|
||||||
auto segj = segments[sej];
|
auto segj = segments[sej];
|
||||||
if (type == 0) {
|
if (type == 0)
|
||||||
auto addSegment = [&](PointIndex p0, PointIndex p1,
|
{
|
||||||
bool extra_edge_nr = false) {
|
auto addSegment = [&] (PointIndex p0, PointIndex p1, bool extra_edge_nr = false) {
|
||||||
Segment s;
|
Segment s;
|
||||||
s[0] = p0;
|
s[0] = p0;
|
||||||
s[1] = p1;
|
s[1] = p1;
|
||||||
@ -656,7 +719,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
if (g0.Size() == 1 && g1.Size() == 1)
|
if (g0.Size() == 1 && g1.Size() == 1)
|
||||||
auto s =
|
auto s =
|
||||||
addSegment(newPoint(p0, -1, g0[0]), newPoint(p1, -1, g1[0]));
|
addSegment(newPoint(p0, -1, g0[0]), newPoint(p1, -1, g1[0]));
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
if (g0.Size() == 2)
|
if (g0.Size() == 2)
|
||||||
addSegment(newPoint(p0, -1, g0[0]), newPoint(p0, -1, g0[1]));
|
addSegment(newPoint(p0, -1, g0[0]), newPoint(p0, -1, g0[1]));
|
||||||
if (g1.Size() == 2)
|
if (g1.Size() == 2)
|
||||||
@ -664,10 +728,12 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// here we need to grow the quad elements
|
// here we need to grow the quad elements
|
||||||
else if (type == 1) {
|
else if (type == 1)
|
||||||
|
{
|
||||||
PointIndex pp1 = segj[1];
|
PointIndex pp1 = segj[1];
|
||||||
PointIndex pp2 = segj[0];
|
PointIndex pp2 = segj[0];
|
||||||
if (in_surface_direction.Test(segj.si)) {
|
if (in_surface_direction.Test(segj.si))
|
||||||
|
{
|
||||||
Swap(pp1, pp2);
|
Swap(pp1, pp2);
|
||||||
is_boundary_moved.SetBit(segj.si);
|
is_boundary_moved.SetBit(segj.si);
|
||||||
}
|
}
|
||||||
@ -684,7 +750,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
if (type == 3)
|
if (type == 3)
|
||||||
new_segments_on_moved_bnd.Append(s0);
|
new_segments_on_moved_bnd.Append(s0);
|
||||||
|
|
||||||
for (auto i : Range(par_heights)) {
|
for (auto i : Range(par_heights))
|
||||||
|
{
|
||||||
Element2d sel(QUAD);
|
Element2d sel(QUAD);
|
||||||
p3 = newPoint(pp2, i);
|
p3 = newPoint(pp2, i);
|
||||||
p4 = newPoint(pp1, i);
|
p4 = newPoint(pp1, i);
|
||||||
@ -692,7 +759,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
sel[1] = p2;
|
sel[1] = p2;
|
||||||
sel[2] = p3;
|
sel[2] = p3;
|
||||||
sel[3] = p4;
|
sel[3] = p4;
|
||||||
for (auto i : Range(4)) {
|
for (auto i : Range(4))
|
||||||
|
{
|
||||||
sel.GeomInfo()[i].u = 0.0;
|
sel.GeomInfo()[i].u = 0.0;
|
||||||
sel.GeomInfo()[i].v = 0.0;
|
sel.GeomInfo()[i].v = 0.0;
|
||||||
}
|
}
|
||||||
@ -730,17 +798,21 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
new_segments.Append(s3);
|
new_segments.Append(s3);
|
||||||
if (type == 3)
|
if (type == 3)
|
||||||
new_segments_on_moved_bnd.Append(s0);
|
new_segments_on_moved_bnd.Append(s0);
|
||||||
} else if (type == 3) {
|
}
|
||||||
|
else if (type == 3)
|
||||||
|
{
|
||||||
PointIndex pp1 = segj[1];
|
PointIndex pp1 = segj[1];
|
||||||
PointIndex pp2 = segj[0];
|
PointIndex pp2 = segj[0];
|
||||||
if (!in_surface_direction.Test(segj.si)) {
|
if (!in_surface_direction.Test(segj.si))
|
||||||
|
{
|
||||||
Swap(pp1, pp2);
|
Swap(pp1, pp2);
|
||||||
}
|
}
|
||||||
PointIndex p1 = pp1;
|
PointIndex p1 = pp1;
|
||||||
PointIndex p2 = pp2;
|
PointIndex p2 = pp2;
|
||||||
PointIndex p3, p4;
|
PointIndex p3, p4;
|
||||||
|
|
||||||
for (auto i : Range(par_heights)) {
|
for (auto i : Range(par_heights))
|
||||||
|
{
|
||||||
Element2d sel(QUAD);
|
Element2d sel(QUAD);
|
||||||
p3 = newPoint(pp2, i);
|
p3 = newPoint(pp2, i);
|
||||||
p4 = newPoint(pp1, i);
|
p4 = newPoint(pp1, i);
|
||||||
@ -748,7 +820,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
sel[1] = p2;
|
sel[1] = p2;
|
||||||
sel[2] = p3;
|
sel[2] = p3;
|
||||||
sel[3] = p4;
|
sel[3] = p4;
|
||||||
for (auto i : Range(4)) {
|
for (auto i : Range(4))
|
||||||
|
{
|
||||||
sel.GeomInfo()[i].u = 0.0;
|
sel.GeomInfo()[i].u = 0.0;
|
||||||
sel.GeomInfo()[i].v = 0.0;
|
sel.GeomInfo()[i].v = 0.0;
|
||||||
}
|
}
|
||||||
@ -783,10 +856,12 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
BitArray fixed_points(np + 1);
|
BitArray fixed_points(np + 1);
|
||||||
fixed_points.Clear();
|
fixed_points.Clear();
|
||||||
auto p2el = mesh.CreatePoint2ElementTable();
|
auto p2el = mesh.CreatePoint2ElementTable();
|
||||||
for (SurfaceElementIndex si = 0; si < nse; si++) {
|
for (SurfaceElementIndex si = 0; si < nse; si++)
|
||||||
|
{
|
||||||
// copy because surfaceels array will be resized!
|
// copy because surfaceels array will be resized!
|
||||||
const auto sel = mesh[si];
|
const auto sel = mesh[si];
|
||||||
if (moved_surfaces.Test(sel.GetIndex())) {
|
if (moved_surfaces.Test(sel.GetIndex()))
|
||||||
|
{
|
||||||
Array<PointIndex> points(sel.PNums());
|
Array<PointIndex> points(sel.PNums());
|
||||||
if (surfacefacs[sel.GetIndex()] > 0)
|
if (surfacefacs[sel.GetIndex()] > 0)
|
||||||
Swap(points[0], points[2]);
|
Swap(points[0], points[2]);
|
||||||
@ -797,7 +872,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
for (auto pi : sel.PNums())
|
for (auto pi : sel.PNums())
|
||||||
if (numGroups(pi) > 1)
|
if (numGroups(pi) > 1)
|
||||||
add_volume_element = false;
|
add_volume_element = false;
|
||||||
for (auto j : Range(par_heights)) {
|
for (auto j : Range(par_heights))
|
||||||
|
{
|
||||||
auto eltype = points.Size() == 3 ? PRISM : HEX;
|
auto eltype = points.Size() == 3 ? PRISM : HEX;
|
||||||
Element el(eltype);
|
Element el(eltype);
|
||||||
for (auto i : Range(points))
|
for (auto i : Range(points))
|
||||||
@ -810,13 +886,12 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
el[sel.PNums().Size() + i] = points[i];
|
el[sel.PNums().Size() + i] = points[i];
|
||||||
auto new_index = new_mat_nrs[sel.GetIndex()];
|
auto new_index = new_mat_nrs[sel.GetIndex()];
|
||||||
if (new_index == -1)
|
if (new_index == -1)
|
||||||
throw Exception("Boundary " + ToString(sel.GetIndex()) +
|
throw Exception("Boundary " + ToString(sel.GetIndex()) + " with name " + mesh.GetBCName(sel.GetIndex() - 1) + " extruded, but no new material specified for it!");
|
||||||
" with name " + mesh.GetBCName(sel.GetIndex() - 1) +
|
|
||||||
" extruded, but no new material specified for it!");
|
|
||||||
el.SetIndex(new_mat_nrs[sel.GetIndex()]);
|
el.SetIndex(new_mat_nrs[sel.GetIndex()]);
|
||||||
if (add_volume_element)
|
if (add_volume_element)
|
||||||
mesh.AddVolumeElement(el);
|
mesh.AddVolumeElement(el);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// Let the volume mesher fill the hole with pyramids/tets
|
// Let the volume mesher fill the hole with pyramids/tets
|
||||||
// To insert pyramids, we need close surface identifications on open
|
// To insert pyramids, we need close surface identifications on open
|
||||||
// quads
|
// quads
|
||||||
@ -831,16 +906,19 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
newel.SetIndex(si_map[sel.GetIndex()]);
|
newel.SetIndex(si_map[sel.GetIndex()]);
|
||||||
new_sels.Append(newel);
|
new_sels.Append(newel);
|
||||||
}
|
}
|
||||||
if (is_boundary_moved.Test(sel.GetIndex())) {
|
if (is_boundary_moved.Test(sel.GetIndex()))
|
||||||
|
{
|
||||||
for (auto& p : mesh[si].PNums())
|
for (auto& p : mesh[si].PNums())
|
||||||
if (hasMoved(p))
|
if (hasMoved(p))
|
||||||
p = newPoint(p);
|
p = newPoint(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SegmentIndex sei = 0; sei < nseg; sei++) {
|
for (SegmentIndex sei = 0; sei < nseg; sei++)
|
||||||
|
{
|
||||||
auto& seg = segments[sei];
|
auto& seg = segments[sei];
|
||||||
if (is_boundary_moved.Test(seg.si)) {
|
if (is_boundary_moved.Test(seg.si))
|
||||||
|
{
|
||||||
// cout << "moved setg " << seg << endl;
|
// cout << "moved setg " << seg << endl;
|
||||||
for (auto& p : seg.PNums())
|
for (auto& p : seg.PNums())
|
||||||
if (hasMoved(p))
|
if (hasMoved(p))
|
||||||
@ -858,7 +936,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
},
|
},
|
||||||
mesh.GetNP());
|
mesh.GetNP());
|
||||||
|
|
||||||
for (auto &[special_pi, special_point] : special_boundary_points) {
|
for (auto& [special_pi, special_point] : special_boundary_points)
|
||||||
|
{
|
||||||
if (special_point.growth_groups.Size() != 2)
|
if (special_point.growth_groups.Size() != 2)
|
||||||
throw Exception("special_point.growth_groups.Size() != 2");
|
throw Exception("special_point.growth_groups.Size() != 2");
|
||||||
|
|
||||||
@ -868,7 +947,8 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
// to). At exactly these points we need to insert new surface elements to
|
// to). At exactly these points we need to insert new surface elements to
|
||||||
// fill the hole.
|
// fill the hole.
|
||||||
std::map<int, std::array<std::set<PointIndex>, 2>> close_group;
|
std::map<int, std::array<std::set<PointIndex>, 2>> close_group;
|
||||||
for (auto sei : p2sel[special_pi]) {
|
for (auto sei : p2sel[special_pi])
|
||||||
|
{
|
||||||
const auto& sel = mesh[sei];
|
const auto& sel = mesh[sei];
|
||||||
for (auto p : sel.PNums())
|
for (auto p : sel.PNums())
|
||||||
if (p != special_pi)
|
if (p != special_pi)
|
||||||
@ -876,19 +956,22 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
p);
|
p);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto [fi, groups] : close_group) {
|
for (auto [fi, groups] : close_group)
|
||||||
|
{
|
||||||
const auto mapped_fi = si_map[fi];
|
const auto mapped_fi = si_map[fi];
|
||||||
std::set<PointIndex> common_points;
|
std::set<PointIndex> common_points;
|
||||||
for (auto pi : groups[0])
|
for (auto pi : groups[0])
|
||||||
if (groups[1].count(pi) == 1)
|
if (groups[1].count(pi) == 1)
|
||||||
common_points.insert(pi);
|
common_points.insert(pi);
|
||||||
if (common_points.size() > 0) {
|
if (common_points.size() > 0)
|
||||||
|
{
|
||||||
auto pi_common = mapto[*common_points.begin()].Last();
|
auto pi_common = mapto[*common_points.begin()].Last();
|
||||||
auto new_special_pi0 = special_point.growth_groups[0].new_points.Last();
|
auto new_special_pi0 = special_point.growth_groups[0].new_points.Last();
|
||||||
auto new_special_pi1 = special_point.growth_groups[1].new_points.Last();
|
auto new_special_pi1 = special_point.growth_groups[1].new_points.Last();
|
||||||
for (auto sei : p2sel[pi_common]) {
|
for (auto sei : p2sel[pi_common])
|
||||||
if (mesh[sei].GetIndex() == mapped_fi &&
|
{
|
||||||
mesh[sei].PNums().Contains(new_special_pi0)) {
|
if (mesh[sei].GetIndex() == mapped_fi && mesh[sei].PNums().Contains(new_special_pi0))
|
||||||
|
{
|
||||||
auto sel = mesh[sei];
|
auto sel = mesh[sei];
|
||||||
sel.Invert();
|
sel.Invert();
|
||||||
for (auto& pi : sel.PNums())
|
for (auto& pi : sel.PNums())
|
||||||
@ -901,10 +984,12 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &[pi, special_point] : special_boundary_points) {
|
for (auto& [pi, special_point] : special_boundary_points)
|
||||||
|
{
|
||||||
if (special_point.growth_groups.Size() != 2)
|
if (special_point.growth_groups.Size() != 2)
|
||||||
throw Exception("special_point.growth_groups.Size() != 2");
|
throw Exception("special_point.growth_groups.Size() != 2");
|
||||||
for (auto igroup : Range(2)) {
|
for (auto igroup : Range(2))
|
||||||
|
{
|
||||||
auto& group = special_point.growth_groups[igroup];
|
auto& group = special_point.growth_groups[igroup];
|
||||||
std::set<int> faces;
|
std::set<int> faces;
|
||||||
for (auto face : group.faces)
|
for (auto face : group.faces)
|
||||||
@ -915,19 +1000,23 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
for (auto sei : p2sel[pi_new])
|
for (auto sei : p2sel[pi_new])
|
||||||
faces.erase(mesh[sei].GetIndex());
|
faces.erase(mesh[sei].GetIndex());
|
||||||
for (auto face : faces)
|
for (auto face : faces)
|
||||||
for (auto seg : new_segments) {
|
for (auto seg : new_segments)
|
||||||
|
{
|
||||||
if ( // seg.si == face
|
if ( // seg.si == face
|
||||||
(seg[0] == pi_new || seg[1] == pi_new) &&
|
(seg[0] == pi_new || seg[1] == pi_new) && (seg[0] != pi_new_other && seg[1] != pi_new_other))
|
||||||
(seg[0] != pi_new_other && seg[1] != pi_new_other)) {
|
{
|
||||||
bool is_correct_face = false;
|
bool is_correct_face = false;
|
||||||
auto pi_other = seg[0] == pi_new ? seg[1] : seg[0];
|
auto pi_other = seg[0] == pi_new ? seg[1] : seg[0];
|
||||||
for (auto sei : p2sel[pi_other]) {
|
for (auto sei : p2sel[pi_other])
|
||||||
if (mesh[sei].GetIndex() == face) {
|
{
|
||||||
|
if (mesh[sei].GetIndex() == face)
|
||||||
|
{
|
||||||
is_correct_face = true;
|
is_correct_face = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_correct_face) {
|
if (is_correct_face)
|
||||||
|
{
|
||||||
Element2d sel;
|
Element2d sel;
|
||||||
sel[0] = seg[1];
|
sel[0] = seg[1];
|
||||||
sel[1] = seg[0];
|
sel[1] = seg[0];
|
||||||
@ -941,11 +1030,13 @@ void BoundaryLayerTool ::InsertNewElements(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::SetDomInOut() {
|
void BoundaryLayerTool ::SetDomInOut()
|
||||||
|
{
|
||||||
if (insert_only_volume_elements)
|
if (insert_only_volume_elements)
|
||||||
return;
|
return;
|
||||||
for (auto i : Range(1, nfd_old + 1))
|
for (auto i : Range(1, nfd_old + 1))
|
||||||
if (moved_surfaces.Test(i)) {
|
if (moved_surfaces.Test(i))
|
||||||
|
{
|
||||||
if (auto dom = mesh.GetFaceDescriptor(si_map[i]).DomainIn();
|
if (auto dom = mesh.GetFaceDescriptor(si_map[i]).DomainIn();
|
||||||
dom > ndom_old)
|
dom > ndom_old)
|
||||||
mesh.GetFaceDescriptor(i).SetDomainOut(dom);
|
mesh.GetFaceDescriptor(i).SetDomainOut(dom);
|
||||||
@ -955,12 +1046,14 @@ void BoundaryLayerTool ::SetDomInOut() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::SetDomInOutSides() {
|
void BoundaryLayerTool ::SetDomInOutSides()
|
||||||
|
{
|
||||||
if (insert_only_volume_elements)
|
if (insert_only_volume_elements)
|
||||||
return;
|
return;
|
||||||
BitArray done(mesh.GetNFD() + 1);
|
BitArray done(mesh.GetNFD() + 1);
|
||||||
done.Clear();
|
done.Clear();
|
||||||
for (auto sei : Range(mesh.SurfaceElements())) {
|
for (auto sei : Range(mesh.SurfaceElements()))
|
||||||
|
{
|
||||||
auto& sel = mesh[sei];
|
auto& sel = mesh[sei];
|
||||||
auto index = sel.GetIndex();
|
auto index = sel.GetIndex();
|
||||||
if (done.Test(index))
|
if (done.Test(index))
|
||||||
@ -982,48 +1075,56 @@ void BoundaryLayerTool ::SetDomInOutSides() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::AddSegments() {
|
void BoundaryLayerTool ::AddSegments()
|
||||||
|
{
|
||||||
auto& new_segs =
|
auto& new_segs =
|
||||||
insert_only_volume_elements ? new_segments_on_moved_bnd : new_segments;
|
insert_only_volume_elements ? new_segments_on_moved_bnd : new_segments;
|
||||||
// cout << "add new segs " << endl << new_segs << endl;
|
// cout << "add new segs " << endl << new_segs << endl;
|
||||||
if (have_single_segments)
|
if (have_single_segments)
|
||||||
MergeAndAddSegments(mesh, segments, new_segs);
|
MergeAndAddSegments(mesh, segments, new_segs);
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
mesh.LineSegments() = segments;
|
mesh.LineSegments() = segments;
|
||||||
for (auto& seg : new_segs)
|
for (auto& seg : new_segs)
|
||||||
mesh.AddSegment(seg);
|
mesh.AddSegment(seg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::AddSurfaceElements() {
|
void BoundaryLayerTool ::AddSurfaceElements()
|
||||||
|
{
|
||||||
for (auto& sel :
|
for (auto& sel :
|
||||||
insert_only_volume_elements ? new_sels_on_moved_bnd : new_sels)
|
insert_only_volume_elements ? new_sels_on_moved_bnd : new_sels)
|
||||||
mesh.AddSurfaceElement(sel);
|
mesh.AddSurfaceElement(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::ProcessParameters() {
|
void BoundaryLayerTool ::ProcessParameters()
|
||||||
if (int *bc = get_if<int>(¶ms.boundary); bc) {
|
{
|
||||||
|
if (int* bc = get_if<int>(¶ms.boundary); bc)
|
||||||
|
{
|
||||||
for (int i = 1; i <= mesh.GetNFD(); i++)
|
for (int i = 1; i <= mesh.GetNFD(); i++)
|
||||||
if (mesh.GetFaceDescriptor(i).BCProperty() == *bc)
|
if (mesh.GetFaceDescriptor(i).BCProperty() == *bc)
|
||||||
par_surfid.Append(i);
|
par_surfid.Append(i);
|
||||||
} else if (string *s = get_if<string>(¶ms.boundary); s) {
|
}
|
||||||
|
else if (string* s = get_if<string>(¶ms.boundary); s)
|
||||||
|
{
|
||||||
regex pattern(*s);
|
regex pattern(*s);
|
||||||
BitArray boundaries(mesh.GetNFD() + 1);
|
BitArray boundaries(mesh.GetNFD() + 1);
|
||||||
boundaries.Clear();
|
boundaries.Clear();
|
||||||
for (int i = 1; i <= mesh.GetNFD(); i++) {
|
for (int i = 1; i <= mesh.GetNFD(); i++)
|
||||||
|
{
|
||||||
auto& fd = mesh.GetFaceDescriptor(i);
|
auto& fd = mesh.GetFaceDescriptor(i);
|
||||||
if (regex_match(fd.GetBCName(), pattern)) {
|
if (regex_match(fd.GetBCName(), pattern))
|
||||||
|
{
|
||||||
boundaries.SetBit(i);
|
boundaries.SetBit(i);
|
||||||
auto dom_pattern = get_if<string>(¶ms.domain);
|
auto dom_pattern = get_if<string>(¶ms.domain);
|
||||||
// only add if adjacent to domain
|
// only add if adjacent to domain
|
||||||
if (dom_pattern) {
|
if (dom_pattern)
|
||||||
|
{
|
||||||
regex pattern(*dom_pattern);
|
regex pattern(*dom_pattern);
|
||||||
bool mat1_match =
|
bool mat1_match =
|
||||||
fd.DomainIn() > 0 &&
|
fd.DomainIn() > 0 && regex_match(mesh.GetMaterial(fd.DomainIn()), pattern);
|
||||||
regex_match(mesh.GetMaterial(fd.DomainIn()), pattern);
|
|
||||||
bool mat2_match =
|
bool mat2_match =
|
||||||
fd.DomainOut() > 0 &&
|
fd.DomainOut() > 0 && regex_match(mesh.GetMaterial(fd.DomainOut()), pattern);
|
||||||
regex_match(mesh.GetMaterial(fd.DomainOut()), pattern);
|
|
||||||
// if boundary is inner or outer remove from list
|
// if boundary is inner or outer remove from list
|
||||||
if (mat1_match == mat2_match)
|
if (mat1_match == mat2_match)
|
||||||
boundaries.Clear(i);
|
boundaries.Clear(i);
|
||||||
@ -1041,36 +1142,46 @@ void BoundaryLayerTool ::ProcessParameters() {
|
|||||||
for (int i = 1; i <= mesh.GetNFD(); i++)
|
for (int i = 1; i <= mesh.GetNFD(); i++)
|
||||||
if (boundaries.Test(i))
|
if (boundaries.Test(i))
|
||||||
par_surfid.Append(i);
|
par_surfid.Append(i);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
auto& surfids = *get_if<std::vector<int>>(¶ms.boundary);
|
auto& surfids = *get_if<std::vector<int>>(¶ms.boundary);
|
||||||
for (auto id : surfids)
|
for (auto id : surfids)
|
||||||
par_surfid.Append(id);
|
par_surfid.Append(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_only_volume_elements = !params.new_material.has_value();
|
insert_only_volume_elements = !params.new_material.has_value();
|
||||||
if (params.new_material) {
|
if (params.new_material)
|
||||||
|
{
|
||||||
if (string* mat = get_if<string>(&*params.new_material); mat)
|
if (string* mat = get_if<string>(&*params.new_material); mat)
|
||||||
par_new_mat = {{".*", *mat}};
|
par_new_mat = {{".*", *mat}};
|
||||||
else
|
else
|
||||||
par_new_mat = *get_if<map<string, string>>(&*params.new_material);
|
par_new_mat = *get_if<map<string, string>>(&*params.new_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.project_boundaries.has_value()) {
|
if (params.project_boundaries.has_value())
|
||||||
|
{
|
||||||
auto proj_bnd = *params.project_boundaries;
|
auto proj_bnd = *params.project_boundaries;
|
||||||
if (string *s = get_if<string>(&proj_bnd); s) {
|
if (string* s = get_if<string>(&proj_bnd); s)
|
||||||
|
{
|
||||||
regex pattern(*s);
|
regex pattern(*s);
|
||||||
for (int i = 1; i <= mesh.GetNFD(); i++)
|
for (int i = 1; i <= mesh.GetNFD(); i++)
|
||||||
if (regex_match(mesh.GetFaceDescriptor(i).GetBCName(), pattern))
|
if (regex_match(mesh.GetFaceDescriptor(i).GetBCName(), pattern))
|
||||||
par_project_boundaries.Append(i);
|
par_project_boundaries.Append(i);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (auto id : *get_if<std::vector<int>>(&proj_bnd))
|
for (auto id : *get_if<std::vector<int>>(&proj_bnd))
|
||||||
par_project_boundaries.Append(id);
|
par_project_boundaries.Append(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (double *height = get_if<double>(¶ms.thickness); height) {
|
if (double* height = get_if<double>(¶ms.thickness); height)
|
||||||
|
{
|
||||||
par_heights.Append(*height);
|
par_heights.Append(*height);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
auto& heights = *get_if<std::vector<double>>(¶ms.thickness);
|
auto& heights = *get_if<std::vector<double>>(¶ms.thickness);
|
||||||
for (auto val : heights)
|
for (auto val : heights)
|
||||||
par_heights.Append(val);
|
par_heights.Append(val);
|
||||||
@ -1079,14 +1190,19 @@ void BoundaryLayerTool ::ProcessParameters() {
|
|||||||
int nr_domains = mesh.GetNDomains();
|
int nr_domains = mesh.GetNDomains();
|
||||||
domains.SetSize(nr_domains + 1); // one based
|
domains.SetSize(nr_domains + 1); // one based
|
||||||
domains.Clear();
|
domains.Clear();
|
||||||
if (string *pdomain = get_if<string>(¶ms.domain); pdomain) {
|
if (string* pdomain = get_if<string>(¶ms.domain); pdomain)
|
||||||
|
{
|
||||||
regex pattern(*pdomain);
|
regex pattern(*pdomain);
|
||||||
for (auto i : Range(1, nr_domains + 1))
|
for (auto i : Range(1, nr_domains + 1))
|
||||||
if (regex_match(mesh.GetMaterial(i), pattern))
|
if (regex_match(mesh.GetMaterial(i), pattern))
|
||||||
domains.SetBit(i);
|
domains.SetBit(i);
|
||||||
} else if (int *idomain = get_if<int>(¶ms.domain); idomain) {
|
}
|
||||||
|
else if (int* idomain = get_if<int>(¶ms.domain); idomain)
|
||||||
|
{
|
||||||
domains.SetBit(*idomain);
|
domains.SetBit(*idomain);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (auto i : *get_if<std::vector<int>>(¶ms.domain))
|
for (auto i : *get_if<std::vector<int>>(¶ms.domain))
|
||||||
domains.SetBit(i);
|
domains.SetBit(i);
|
||||||
}
|
}
|
||||||
@ -1106,14 +1222,18 @@ void BoundaryLayerTool ::ProcessParameters() {
|
|||||||
|
|
||||||
new_mat_nrs.SetSize(mesh.FaceDescriptors().Size() + 1);
|
new_mat_nrs.SetSize(mesh.FaceDescriptors().Size() + 1);
|
||||||
new_mat_nrs = -1;
|
new_mat_nrs = -1;
|
||||||
if (insert_only_volume_elements) {
|
if (insert_only_volume_elements)
|
||||||
for (auto i : Range(1, mesh.GetNFD() + 1)) {
|
{
|
||||||
|
for (auto i : Range(1, mesh.GetNFD() + 1))
|
||||||
|
{
|
||||||
auto& fd = mesh.GetFaceDescriptor(i);
|
auto& fd = mesh.GetFaceDescriptor(i);
|
||||||
auto domin = fd.DomainIn();
|
auto domin = fd.DomainIn();
|
||||||
auto domout = fd.DomainOut();
|
auto domout = fd.DomainOut();
|
||||||
for (int dom : {domin, domout})
|
for (int dom : {domin, domout})
|
||||||
if (domains.Test(dom)) {
|
if (domains.Test(dom))
|
||||||
if (params.outside) {
|
{
|
||||||
|
if (params.outside)
|
||||||
|
{
|
||||||
dom = domin + domout - dom;
|
dom = domin + domout - dom;
|
||||||
if (dom == 0)
|
if (dom == 0)
|
||||||
throw NG_EXCEPTION("No new material specified for boundarylayer "
|
throw NG_EXCEPTION("No new material specified for boundarylayer "
|
||||||
@ -1122,11 +1242,15 @@ void BoundaryLayerTool ::ProcessParameters() {
|
|||||||
new_mat_nrs[i] = dom;
|
new_mat_nrs[i] = dom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
for (auto [bcname, matname] : par_new_mat) {
|
else
|
||||||
|
{
|
||||||
|
for (auto [bcname, matname] : par_new_mat)
|
||||||
|
{
|
||||||
mesh.SetMaterial(++ndom, matname);
|
mesh.SetMaterial(++ndom, matname);
|
||||||
regex pattern(bcname);
|
regex pattern(bcname);
|
||||||
for (auto i : Range(1, mesh.GetNFD() + 1)) {
|
for (auto i : Range(1, mesh.GetNFD() + 1))
|
||||||
|
{
|
||||||
auto& fd = mesh.GetFaceDescriptor(i);
|
auto& fd = mesh.GetFaceDescriptor(i);
|
||||||
if (regex_match(fd.GetBCName(), pattern))
|
if (regex_match(fd.GetBCName(), pattern))
|
||||||
new_mat_nrs[i] = ndom;
|
new_mat_nrs[i] = ndom;
|
||||||
@ -1138,7 +1262,8 @@ void BoundaryLayerTool ::ProcessParameters() {
|
|||||||
domains.Invert();
|
domains.Invert();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::Perform() {
|
void BoundaryLayerTool ::Perform()
|
||||||
|
{
|
||||||
CreateNewFaceDescriptors();
|
CreateNewFaceDescriptors();
|
||||||
CalculateGrowthVectors();
|
CalculateGrowthVectors();
|
||||||
CreateFaceDescriptorsSides();
|
CreateFaceDescriptorsSides();
|
||||||
@ -1165,7 +1290,8 @@ void BoundaryLayerTool ::Perform() {
|
|||||||
|
|
||||||
FixSurfaceElements();
|
FixSurfaceElements();
|
||||||
|
|
||||||
for (auto [pi, data] : growth_vector_map) {
|
for (auto [pi, data] : growth_vector_map)
|
||||||
|
{
|
||||||
auto [gw, height] = data;
|
auto [gw, height] = data;
|
||||||
mesh[pi] += height * (*gw);
|
mesh[pi] += height * (*gw);
|
||||||
}
|
}
|
||||||
@ -1177,7 +1303,8 @@ void BoundaryLayerTool ::Perform() {
|
|||||||
SetDomInOutSides();
|
SetDomInOutSides();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateBoundaryLayer(Mesh &mesh, const BoundaryLayerParameters &blp) {
|
void GenerateBoundaryLayer (Mesh& mesh, const BoundaryLayerParameters& blp)
|
||||||
|
{
|
||||||
static Timer timer("Create Boundarylayers");
|
static Timer timer("Create Boundarylayers");
|
||||||
RegionTimer regt(timer);
|
RegionTimer regt(timer);
|
||||||
|
|
||||||
|
@ -14,8 +14,10 @@ DLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh & mesh);
|
|||||||
/// Create a typical prismatic boundary layer on the given
|
/// Create a typical prismatic boundary layer on the given
|
||||||
/// surfaces
|
/// surfaces
|
||||||
|
|
||||||
struct SpecialBoundaryPoint {
|
struct SpecialBoundaryPoint
|
||||||
struct GrowthGroup {
|
{
|
||||||
|
struct GrowthGroup
|
||||||
|
{
|
||||||
Array<int> faces;
|
Array<int> faces;
|
||||||
Vec<3> growth_vector;
|
Vec<3> growth_vector;
|
||||||
Array<PointIndex> new_points;
|
Array<PointIndex> new_points;
|
||||||
@ -23,7 +25,6 @@ struct SpecialBoundaryPoint {
|
|||||||
GrowthGroup(FlatArray<int> faces_, FlatArray<Vec<3>> normals);
|
GrowthGroup(FlatArray<int> faces_, FlatArray<Vec<3>> normals);
|
||||||
GrowthGroup(const GrowthGroup&) = default;
|
GrowthGroup(const GrowthGroup&) = default;
|
||||||
GrowthGroup() = default;
|
GrowthGroup() = default;
|
||||||
|
|
||||||
};
|
};
|
||||||
// std::map<int, Vec<3>> normals;
|
// std::map<int, Vec<3>> normals;
|
||||||
Array<GrowthGroup> growth_groups;
|
Array<GrowthGroup> growth_groups;
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include "boundarylayer.hpp"
|
#include "boundarylayer.hpp"
|
||||||
|
|
||||||
namespace netgen {
|
namespace netgen
|
||||||
|
{
|
||||||
|
|
||||||
namespace detail {
|
namespace detail
|
||||||
struct Neighbor {
|
{
|
||||||
|
struct Neighbor
|
||||||
|
{
|
||||||
PointIndex pi;
|
PointIndex pi;
|
||||||
SurfaceElementIndex sei;
|
SurfaceElementIndex sei;
|
||||||
double weight;
|
double weight;
|
||||||
@ -11,34 +14,39 @@ struct Neighbor {
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
Array<ArrayMem<detail::Neighbor, 20>>
|
Array<ArrayMem<detail::Neighbor, 20>>
|
||||||
BuildNeighbors(FlatArray<PointIndex> points, const Mesh &mesh) {
|
BuildNeighbors (FlatArray<PointIndex> points, const Mesh& mesh)
|
||||||
|
{
|
||||||
auto p2sel = mesh.CreatePoint2SurfaceElementTable();
|
auto p2sel = mesh.CreatePoint2SurfaceElementTable();
|
||||||
|
|
||||||
Array<ArrayMem<detail::Neighbor, 20>> neighbors(points.Size());
|
Array<ArrayMem<detail::Neighbor, 20>> neighbors(points.Size());
|
||||||
|
|
||||||
ArrayMem<double, 20> angles;
|
ArrayMem<double, 20> angles;
|
||||||
ArrayMem<double, 20> inv_dists;
|
ArrayMem<double, 20> inv_dists;
|
||||||
for (auto i : points.Range()) {
|
for (auto i : points.Range())
|
||||||
|
{
|
||||||
auto& p_neighbors = neighbors[i];
|
auto& p_neighbors = neighbors[i];
|
||||||
auto pi = points[i];
|
auto pi = points[i];
|
||||||
angles.SetSize(0);
|
angles.SetSize(0);
|
||||||
inv_dists.SetSize(0);
|
inv_dists.SetSize(0);
|
||||||
for (auto sei : p2sel[pi]) {
|
for (auto sei : p2sel[pi])
|
||||||
|
{
|
||||||
const auto& sel = mesh[sei];
|
const auto& sel = mesh[sei];
|
||||||
for (auto pi1 : sel.PNums()) {
|
for (auto pi1 : sel.PNums())
|
||||||
|
{
|
||||||
if (pi1 == pi)
|
if (pi1 == pi)
|
||||||
continue;
|
continue;
|
||||||
auto pi2 = pi1;
|
auto pi2 = pi1;
|
||||||
for (auto pi_ : sel.PNums()) {
|
for (auto pi_ : sel.PNums())
|
||||||
if (pi_ != pi && pi_ != pi1) {
|
{
|
||||||
|
if (pi_ != pi && pi_ != pi1)
|
||||||
|
{
|
||||||
pi2 = pi_;
|
pi2 = pi_;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p_neighbors.Append({pi1, sei, 0.0});
|
p_neighbors.Append({pi1, sei, 0.0});
|
||||||
inv_dists.Append(1.0 / (mesh[pi1] - mesh[pi]).Length());
|
inv_dists.Append(1.0 / (mesh[pi1] - mesh[pi]).Length());
|
||||||
auto dot = (mesh[pi1] - mesh[pi]).Normalize() *
|
auto dot = (mesh[pi1] - mesh[pi]).Normalize() * (mesh[pi2] - mesh[pi]).Normalize();
|
||||||
(mesh[pi2] - mesh[pi]).Normalize();
|
|
||||||
angles.Append(acos(dot));
|
angles.Append(acos(dot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +58,8 @@ BuildNeighbors(FlatArray<PointIndex> points, const Mesh &mesh) {
|
|||||||
sum_angle += angle;
|
sum_angle += angle;
|
||||||
|
|
||||||
double sum_weight = 0.0;
|
double sum_weight = 0.0;
|
||||||
for (auto i : Range(inv_dists)) {
|
for (auto i : Range(inv_dists))
|
||||||
|
{
|
||||||
p_neighbors[i].weight =
|
p_neighbors[i].weight =
|
||||||
inv_dists[i] * angles[i] / sum_inv_dist / sum_angle;
|
inv_dists[i] * angles[i] / sum_inv_dist / sum_angle;
|
||||||
sum_weight += p_neighbors[i].weight;
|
sum_weight += p_neighbors[i].weight;
|
||||||
@ -61,7 +70,8 @@ BuildNeighbors(FlatArray<PointIndex> points, const Mesh &mesh) {
|
|||||||
return neighbors;
|
return neighbors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
void BoundaryLayerTool ::InterpolateGrowthVectors()
|
||||||
|
{
|
||||||
int new_max_edge_nr = max_edge_nr;
|
int new_max_edge_nr = max_edge_nr;
|
||||||
for (const auto& seg : segments)
|
for (const auto& seg : segments)
|
||||||
if (seg.edgenr > new_max_edge_nr)
|
if (seg.edgenr > new_max_edge_nr)
|
||||||
@ -107,7 +117,8 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
},
|
},
|
||||||
mesh.GetNP());
|
mesh.GetNP());
|
||||||
|
|
||||||
for (auto edgenr : Range(max_edge_nr + 1, new_max_edge_nr + 1)) {
|
for (auto edgenr : Range(max_edge_nr + 1, new_max_edge_nr + 1))
|
||||||
|
{
|
||||||
double edge_len = 0.;
|
double edge_len = 0.;
|
||||||
|
|
||||||
auto is_end_point = [&] (PointIndex pi) {
|
auto is_end_point = [&] (PointIndex pi) {
|
||||||
@ -124,7 +135,8 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
bool any_grows = false;
|
bool any_grows = false;
|
||||||
|
|
||||||
Array<PointIndex> points;
|
Array<PointIndex> points;
|
||||||
for (auto *p_seg : edgenr2seg[edgenr]) {
|
for (auto* p_seg : edgenr2seg[edgenr])
|
||||||
|
{
|
||||||
auto& seg = *p_seg;
|
auto& seg = *p_seg;
|
||||||
|
|
||||||
if (getGW(seg[0]).Length2() != 0 || getGW(seg[1]).Length2() != 0)
|
if (getGW(seg[0]).Length2() != 0 || getGW(seg[1]).Length2() != 0)
|
||||||
@ -132,7 +144,8 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
|
|
||||||
if (points.Size() == 0)
|
if (points.Size() == 0)
|
||||||
for (auto i : Range(2))
|
for (auto i : Range(2))
|
||||||
if (is_end_point(seg[i])) {
|
if (is_end_point(seg[i]))
|
||||||
|
{
|
||||||
points.Append(seg[i]);
|
points.Append(seg[i]);
|
||||||
points.Append(seg[1 - i]);
|
points.Append(seg[1 - i]);
|
||||||
edge_len += (mesh[seg[1]] - mesh[seg[0]]).Length();
|
edge_len += (mesh[seg[1]] - mesh[seg[0]]).Length();
|
||||||
@ -140,13 +153,14 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!any_grows) {
|
if (!any_grows)
|
||||||
PrintMessage(1, "BLayer: skip interpolating growth vectors at edge ",
|
{
|
||||||
edgenr + 1);
|
PrintMessage(1, "BLayer: skip interpolating growth vectors at edge ", edgenr + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!points.Size()) {
|
if (!points.Size())
|
||||||
|
{
|
||||||
cerr << "Could not find startpoint for edge " << edgenr << endl;
|
cerr << "Could not find startpoint for edge " << edgenr << endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -156,11 +170,13 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
points_set.insert(points[1]);
|
points_set.insert(points[1]);
|
||||||
|
|
||||||
bool point_found = true;
|
bool point_found = true;
|
||||||
while (point_found) {
|
while (point_found)
|
||||||
|
{
|
||||||
if (is_end_point(points.Last()))
|
if (is_end_point(points.Last()))
|
||||||
break;
|
break;
|
||||||
point_found = false;
|
point_found = false;
|
||||||
for (auto *p_seg : point2seg[points.Last()]) {
|
for (auto* p_seg : point2seg[points.Last()])
|
||||||
|
{
|
||||||
const auto& seg = *p_seg;
|
const auto& seg = *p_seg;
|
||||||
if (seg.edgenr != edgenr)
|
if (seg.edgenr != edgenr)
|
||||||
continue;
|
continue;
|
||||||
@ -168,10 +184,10 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
if (plast != seg[0] && plast != seg[1])
|
if (plast != seg[0] && plast != seg[1])
|
||||||
continue;
|
continue;
|
||||||
auto pnew = plast == seg[0] ? seg[1] : seg[0];
|
auto pnew = plast == seg[0] ? seg[1] : seg[0];
|
||||||
if (pnew == points[0] && points.Size() > 1) {
|
if (pnew == points[0] && points.Size() > 1)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
if (points_set.count(pnew) > 0 &&
|
if (points_set.count(pnew) > 0 && (pnew != points[0] || points.Size() == 2))
|
||||||
(pnew != points[0] || points.Size() == 2))
|
|
||||||
continue;
|
continue;
|
||||||
edge_len += (mesh[points.Last()] - mesh[pnew]).Length();
|
edge_len += (mesh[points.Last()] - mesh[pnew]).Length();
|
||||||
points.Append(pnew);
|
points.Append(pnew);
|
||||||
@ -180,10 +196,12 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!point_found) {
|
if (!point_found)
|
||||||
|
{
|
||||||
cerr << "Could not find connected list of line segments for edge "
|
cerr << "Could not find connected list of line segments for edge "
|
||||||
<< edgenr << endl;
|
<< edgenr << endl;
|
||||||
cerr << "current points: " << endl << points << endl;
|
cerr << "current points: " << endl
|
||||||
|
<< points << endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +216,8 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
auto gt2 = getGW(points.Last()) * t2 * t2;
|
auto gt2 = getGW(points.Last()) * t2 * t2;
|
||||||
|
|
||||||
double len = 0.;
|
double len = 0.;
|
||||||
for (auto i : IntRange(1, points.Size() - 1)) {
|
for (auto i : IntRange(1, points.Size() - 1))
|
||||||
|
{
|
||||||
auto pi = points[i];
|
auto pi = points[i];
|
||||||
len += (mesh[pi] - mesh[points[i - 1]]).Length();
|
len += (mesh[pi] - mesh[points[i - 1]]).Length();
|
||||||
auto t = getEdgeTangent(pi, edgenr, point2seg[pi]);
|
auto t = getEdgeTangent(pi, edgenr, point2seg[pi]);
|
||||||
@ -209,7 +228,8 @@ void BoundaryLayerTool ::InterpolateGrowthVectors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors() {
|
void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors()
|
||||||
|
{
|
||||||
static Timer tall("InterpolateSurfaceGrowthVectors");
|
static Timer tall("InterpolateSurfaceGrowthVectors");
|
||||||
RegionTimer rtall(tall);
|
RegionTimer rtall(tall);
|
||||||
static Timer tsmooth("InterpolateSurfaceGrowthVectors-Smoothing");
|
static Timer tsmooth("InterpolateSurfaceGrowthVectors-Smoothing");
|
||||||
@ -248,13 +268,13 @@ void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto hasMoved = [&] (PointIndex pi) {
|
auto hasMoved = [&] (PointIndex pi) {
|
||||||
return (pi - PointIndex::BASE >= np_old) || mapto[pi].Size() > 0 ||
|
return (pi - PointIndex::BASE >= np_old) || mapto[pi].Size() > 0 || special_boundary_points.count(pi);
|
||||||
special_boundary_points.count(pi);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// cout << __FILE__ << ":" << __LINE__ << endl;
|
// cout << __FILE__ << ":" << __LINE__ << endl;
|
||||||
std::set<PointIndex> points_set;
|
std::set<PointIndex> points_set;
|
||||||
for (const auto &sel : mesh.SurfaceElements()) {
|
for (const auto& sel : mesh.SurfaceElements())
|
||||||
|
{
|
||||||
for (auto pi : sel.PNums())
|
for (auto pi : sel.PNums())
|
||||||
if (mesh[pi].Type() == SURFACEPOINT && hasMoved(pi))
|
if (mesh[pi].Type() == SURFACEPOINT && hasMoved(pi))
|
||||||
points_set.insert(pi);
|
points_set.insert(pi);
|
||||||
@ -277,15 +297,18 @@ void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors() {
|
|||||||
|
|
||||||
BitArray interpolate_tangent(mesh.GetNP() + 1);
|
BitArray interpolate_tangent(mesh.GetNP() + 1);
|
||||||
interpolate_tangent = false;
|
interpolate_tangent = false;
|
||||||
for (auto pi : points) {
|
for (auto pi : points)
|
||||||
|
{
|
||||||
for (auto sei : p2sel[pi])
|
for (auto sei : p2sel[pi])
|
||||||
if (is_boundary_moved[mesh[sei].GetIndex()])
|
if (is_boundary_moved[mesh[sei].GetIndex()])
|
||||||
interpolate_tangent.SetBit(pi);
|
interpolate_tangent.SetBit(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int N_STEPS = 64;
|
constexpr int N_STEPS = 64;
|
||||||
for ([[maybe_unused]] auto i : Range(N_STEPS)) {
|
for ([[maybe_unused]] auto i : Range(N_STEPS))
|
||||||
for (auto i : points.Range()) {
|
{
|
||||||
|
for (auto i : points.Range())
|
||||||
|
{
|
||||||
auto pi = points[i];
|
auto pi = points[i];
|
||||||
// cout << "AVERAGE " << pi << endl;
|
// cout << "AVERAGE " << pi << endl;
|
||||||
auto& p_neighbors = neighbors[i];
|
auto& p_neighbors = neighbors[i];
|
||||||
@ -297,9 +320,11 @@ void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors() {
|
|||||||
// average only tangent component on new bl points, average whole growth
|
// average only tangent component on new bl points, average whole growth
|
||||||
// vector otherwise
|
// vector otherwise
|
||||||
bool do_average_tangent = true;
|
bool do_average_tangent = true;
|
||||||
for (const auto &s : p_neighbors) {
|
for (const auto& s : p_neighbors)
|
||||||
|
{
|
||||||
auto gw_other = getGW(s.pi) + corrections[s.pi];
|
auto gw_other = getGW(s.pi) + corrections[s.pi];
|
||||||
if (do_average_tangent) {
|
if (do_average_tangent)
|
||||||
|
{
|
||||||
auto n = surf_normals[s.sei];
|
auto n = surf_normals[s.sei];
|
||||||
gw_other = gw_other - (gw_other * n) * n;
|
gw_other = gw_other - (gw_other * n) * n;
|
||||||
}
|
}
|
||||||
@ -320,10 +345,10 @@ void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors() {
|
|||||||
|
|
||||||
auto& correction = corrections[pi];
|
auto& correction = corrections[pi];
|
||||||
correction = 0.0;
|
correction = 0.0;
|
||||||
for (const auto i : p_neighbors.Range()) {
|
for (const auto i : p_neighbors.Range())
|
||||||
|
{
|
||||||
auto v = g_vectors[i];
|
auto v = g_vectors[i];
|
||||||
double weight = lambda * p_neighbors[i].weight +
|
double weight = lambda * p_neighbors[i].weight + (1.0 - lambda) * v.Length2() / sum_len;
|
||||||
(1.0 - lambda) * v.Length2() / sum_len;
|
|
||||||
// if(pi == 19911) cout << "pi " << pi << "\tneighbor " <<
|
// if(pi == 19911) cout << "pi " << pi << "\tneighbor " <<
|
||||||
// p_neighbors[i].pi << "\tweight " << weight << endl;
|
// p_neighbors[i].pi << "\tweight " << weight << endl;
|
||||||
correction += weight * v;
|
correction += weight * v;
|
||||||
@ -340,7 +365,8 @@ void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors() {
|
|||||||
addGW(pi, corrections[pi]);
|
addGW(pi, corrections[pi]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundaryLayerTool ::FixSurfaceElements() {
|
void BoundaryLayerTool ::FixSurfaceElements()
|
||||||
|
{
|
||||||
static Timer tall("FixSurfaceElements");
|
static Timer tall("FixSurfaceElements");
|
||||||
RegionTimer rtall(tall);
|
RegionTimer rtall(tall);
|
||||||
auto np_old = this->np;
|
auto np_old = this->np;
|
||||||
@ -350,7 +376,8 @@ void BoundaryLayerTool ::FixSurfaceElements() {
|
|||||||
|
|
||||||
auto getGW = [&] (PointIndex pi) -> Vec<3> {
|
auto getGW = [&] (PointIndex pi) -> Vec<3> {
|
||||||
// return growthvectors[pi];
|
// return growthvectors[pi];
|
||||||
if (growth_vector_map.count(pi) == 0) {
|
if (growth_vector_map.count(pi) == 0)
|
||||||
|
{
|
||||||
non_bl_growth_vectors[pi] = .0;
|
non_bl_growth_vectors[pi] = .0;
|
||||||
growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};
|
growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};
|
||||||
}
|
}
|
||||||
@ -359,7 +386,8 @@ void BoundaryLayerTool ::FixSurfaceElements() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto addGW = [&] (PointIndex pi, Vec<3> vec) {
|
auto addGW = [&] (PointIndex pi, Vec<3> vec) {
|
||||||
if (growth_vector_map.count(pi) == 0) {
|
if (growth_vector_map.count(pi) == 0)
|
||||||
|
{
|
||||||
non_bl_growth_vectors[pi] = .0;
|
non_bl_growth_vectors[pi] = .0;
|
||||||
growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};
|
growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};
|
||||||
}
|
}
|
||||||
@ -369,7 +397,8 @@ void BoundaryLayerTool ::FixSurfaceElements() {
|
|||||||
|
|
||||||
std::set<PointIndex> points_set;
|
std::set<PointIndex> points_set;
|
||||||
// only smooth over old surface elements
|
// only smooth over old surface elements
|
||||||
for (SurfaceElementIndex sei : Range(nse)) {
|
for (SurfaceElementIndex sei : Range(nse))
|
||||||
|
{
|
||||||
const auto& sel = mesh[sei];
|
const auto& sel = mesh[sei];
|
||||||
if (sel.GetNP() == 3 && is_boundary_moved[sel.GetIndex()])
|
if (sel.GetNP() == 3 && is_boundary_moved[sel.GetIndex()])
|
||||||
for (auto pi : sel.PNums())
|
for (auto pi : sel.PNums())
|
||||||
@ -388,8 +417,10 @@ void BoundaryLayerTool ::FixSurfaceElements() {
|
|||||||
auto neighbors = BuildNeighbors(points, mesh);
|
auto neighbors = BuildNeighbors(points, mesh);
|
||||||
|
|
||||||
constexpr int N_STEPS = 32;
|
constexpr int N_STEPS = 32;
|
||||||
for ([[maybe_unused]] auto i : Range(N_STEPS)) {
|
for ([[maybe_unused]] auto i : Range(N_STEPS))
|
||||||
for (auto i : points.Range()) {
|
{
|
||||||
|
for (auto i : points.Range())
|
||||||
|
{
|
||||||
auto pi = points[i];
|
auto pi = points[i];
|
||||||
auto& p_neighbors = neighbors[i];
|
auto& p_neighbors = neighbors[i];
|
||||||
|
|
||||||
@ -397,7 +428,8 @@ void BoundaryLayerTool ::FixSurfaceElements() {
|
|||||||
double max_len = 0.0;
|
double max_len = 0.0;
|
||||||
double sum_len = 0.0;
|
double sum_len = 0.0;
|
||||||
|
|
||||||
for (const auto &s : p_neighbors) {
|
for (const auto& s : p_neighbors)
|
||||||
|
{
|
||||||
auto v = getGW(s.pi) + corrections[s.pi];
|
auto v = getGW(s.pi) + corrections[s.pi];
|
||||||
auto len = v.Length2();
|
auto len = v.Length2();
|
||||||
sum_len += len;
|
sum_len += len;
|
||||||
@ -415,10 +447,10 @@ void BoundaryLayerTool ::FixSurfaceElements() {
|
|||||||
|
|
||||||
auto& correction = corrections[pi];
|
auto& correction = corrections[pi];
|
||||||
correction = 0.0;
|
correction = 0.0;
|
||||||
for (const auto i : p_neighbors.Range()) {
|
for (const auto i : p_neighbors.Range())
|
||||||
|
{
|
||||||
auto v = g_vectors[i];
|
auto v = g_vectors[i];
|
||||||
double weight = lambda * p_neighbors[i].weight +
|
double weight = lambda * p_neighbors[i].weight + (1.0 - lambda) * v.Length2() / sum_len;
|
||||||
(1.0 - lambda) * v.Length2() / sum_len;
|
|
||||||
correction += weight * v;
|
correction += weight * v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include "boundarylayer.hpp"
|
#include "boundarylayer.hpp"
|
||||||
#include <core/array.hpp>
|
#include <core/array.hpp>
|
||||||
|
|
||||||
namespace netgen {
|
namespace netgen
|
||||||
|
{
|
||||||
|
|
||||||
struct Intersection_ {
|
struct Intersection_
|
||||||
|
{
|
||||||
bool is_intersecting = false;
|
bool is_intersecting = false;
|
||||||
double lam0 = -1, lam1 = -1;
|
double lam0 = -1, lam1 = -1;
|
||||||
Point<3> p;
|
Point<3> p;
|
||||||
@ -11,7 +13,8 @@ struct Intersection_ {
|
|||||||
operator bool() const { return is_intersecting; }
|
operator bool() const { return is_intersecting; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GrowthVectorLimiter {
|
struct GrowthVectorLimiter
|
||||||
|
{
|
||||||
typedef std::array<Point<3>, 2> Seg;
|
typedef std::array<Point<3>, 2> Seg;
|
||||||
typedef std::array<Point<3>, 3> Trig;
|
typedef std::array<Point<3>, 3> Trig;
|
||||||
|
|
||||||
@ -27,9 +30,8 @@ struct GrowthVectorLimiter {
|
|||||||
Table<SurfaceElementIndex, PointIndex> p2sel;
|
Table<SurfaceElementIndex, PointIndex> p2sel;
|
||||||
|
|
||||||
GrowthVectorLimiter(BoundaryLayerTool& tool_)
|
GrowthVectorLimiter(BoundaryLayerTool& tool_)
|
||||||
: tool(tool_), params(tool_.params), mesh(tool_.mesh),
|
: tool(tool_), params(tool_.params), mesh(tool_.mesh), height(tool_.total_height), growthvectors(tool_.growthvectors), map_from(mesh.Points().Size())
|
||||||
height(tool_.total_height), growthvectors(tool_.growthvectors),
|
{
|
||||||
map_from(mesh.Points().Size()) {
|
|
||||||
changed_domains = tool.domains;
|
changed_domains = tool.domains;
|
||||||
if (!params.outside)
|
if (!params.outside)
|
||||||
changed_domains.Invert();
|
changed_domains.Invert();
|
||||||
@ -46,17 +48,20 @@ struct GrowthVectorLimiter {
|
|||||||
|
|
||||||
auto SurfaceElementsRange () { return Range(tool.nse + tool.new_sels.Size()); }
|
auto SurfaceElementsRange () { return Range(tool.nse + tool.new_sels.Size()); }
|
||||||
|
|
||||||
const auto &Get(SurfaceElementIndex sei) {
|
const auto& Get (SurfaceElementIndex sei)
|
||||||
|
{
|
||||||
if (sei < tool.nse)
|
if (sei < tool.nse)
|
||||||
return mesh[sei];
|
return mesh[sei];
|
||||||
return tool.new_sels[sei - tool.nse];
|
return tool.new_sels[sei - tool.nse];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<double, double> GetMinMaxLimit(SurfaceElementIndex sei) {
|
std::pair<double, double> GetMinMaxLimit (SurfaceElementIndex sei)
|
||||||
|
{
|
||||||
const auto& sel = Get(sei);
|
const auto& sel = Get(sei);
|
||||||
double min_limit = GetLimit(sel[0]);
|
double min_limit = GetLimit(sel[0]);
|
||||||
double max_limit = min_limit;
|
double max_limit = min_limit;
|
||||||
for (auto i : IntRange(1, sel.GetNP())) {
|
for (auto i : IntRange(1, sel.GetNP()))
|
||||||
|
{
|
||||||
auto limit = GetLimit(sel[i]);
|
auto limit = GetLimit(sel[i]);
|
||||||
min_limit = min(min_limit, limit);
|
min_limit = min(min_limit, limit);
|
||||||
max_limit = max(max_limit, limit);
|
max_limit = max(max_limit, limit);
|
||||||
@ -64,13 +69,15 @@ struct GrowthVectorLimiter {
|
|||||||
return {min_limit, max_limit};
|
return {min_limit, max_limit};
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetLimit(PointIndex pi) {
|
double GetLimit (PointIndex pi)
|
||||||
|
{
|
||||||
if (pi <= tool.np)
|
if (pi <= tool.np)
|
||||||
return limits[pi];
|
return limits[pi];
|
||||||
return limits[map_from[pi]];
|
return limits[map_from[pi]];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetLimit(PointIndex pi, double new_limit) {
|
bool SetLimit (PointIndex pi, double new_limit)
|
||||||
|
{
|
||||||
double& limit = (pi <= tool.np) ? limits[pi] : limits[map_from[pi]];
|
double& limit = (pi <= tool.np) ? limits[pi] : limits[map_from[pi]];
|
||||||
if (limit <= new_limit)
|
if (limit <= new_limit)
|
||||||
return false;
|
return false;
|
||||||
@ -78,42 +85,46 @@ struct GrowthVectorLimiter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScaleLimit(PointIndex pi, double factor) {
|
bool ScaleLimit (PointIndex pi, double factor)
|
||||||
|
{
|
||||||
double& limit = (pi <= tool.np) ? limits[pi] : limits[map_from[pi]];
|
double& limit = (pi <= tool.np) ? limits[pi] : limits[map_from[pi]];
|
||||||
return SetLimit(pi, limit * factor);
|
return SetLimit(pi, limit * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec<3> GetVector(PointIndex pi_to, double shift = 1.,
|
Vec<3> GetVector (PointIndex pi_to, double shift = 1., bool apply_limit = false)
|
||||||
bool apply_limit = false) {
|
{
|
||||||
auto [gw, height] = tool.growth_vector_map[pi_to];
|
auto [gw, height] = tool.growth_vector_map[pi_to];
|
||||||
if (apply_limit)
|
if (apply_limit)
|
||||||
shift *= GetLimit(pi_to);
|
shift *= GetLimit(pi_to);
|
||||||
return shift * height * (*gw);
|
return shift * height * (*gw);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point<3> GetPoint(PointIndex pi_to, double shift = 1.,
|
Point<3> GetPoint (PointIndex pi_to, double shift = 1., bool apply_limit = false)
|
||||||
bool apply_limit = false) {
|
{
|
||||||
if (pi_to <= tool.np || tool.growth_vector_map.count(pi_to) == 0)
|
if (pi_to <= tool.np || tool.growth_vector_map.count(pi_to) == 0)
|
||||||
return mesh[pi_to];
|
return mesh[pi_to];
|
||||||
|
|
||||||
return mesh[pi_to] + GetVector(pi_to, shift, apply_limit);
|
return mesh[pi_to] + GetVector(pi_to, shift, apply_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point<3> GetMappedPoint(PointIndex pi_from, double shift = 1.) {
|
Point<3> GetMappedPoint (PointIndex pi_from, double shift = 1.)
|
||||||
|
{
|
||||||
auto pi_to = tool.mapto[pi_from].Last();
|
auto pi_to = tool.mapto[pi_from].Last();
|
||||||
return GetPoint(pi_to, shift);
|
return GetPoint(pi_to, shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
Seg GetMappedSeg(PointIndex pi_from, double shift = 1.) {
|
Seg GetMappedSeg (PointIndex pi_from, double shift = 1.)
|
||||||
|
{
|
||||||
return {mesh[pi_from], GetMappedPoint(pi_from, shift)};
|
return {mesh[pi_from], GetMappedPoint(pi_from, shift)};
|
||||||
}
|
}
|
||||||
|
|
||||||
Seg GetSeg(PointIndex pi_to, double shift = 1., bool apply_limit = false) {
|
Seg GetSeg (PointIndex pi_to, double shift = 1., bool apply_limit = false)
|
||||||
|
{
|
||||||
return {GetPoint(pi_to, 0), GetPoint(pi_to, shift, apply_limit)};
|
return {GetPoint(pi_to, 0), GetPoint(pi_to, shift, apply_limit)};
|
||||||
}
|
}
|
||||||
|
|
||||||
Trig GetTrig(SurfaceElementIndex sei, double shift = 0.0,
|
Trig GetTrig (SurfaceElementIndex sei, double shift = 0.0, bool apply_limit = false)
|
||||||
bool apply_limit = false) {
|
{
|
||||||
auto sel = Get(sei);
|
auto sel = Get(sei);
|
||||||
Trig trig;
|
Trig trig;
|
||||||
for (auto i : Range(3))
|
for (auto i : Range(3))
|
||||||
@ -121,7 +132,8 @@ struct GrowthVectorLimiter {
|
|||||||
return trig;
|
return trig;
|
||||||
}
|
}
|
||||||
|
|
||||||
Trig GetMappedTrig(SurfaceElementIndex sei, double shift = 0.0) {
|
Trig GetMappedTrig (SurfaceElementIndex sei, double shift = 0.0)
|
||||||
|
{
|
||||||
auto sel = Get(sei);
|
auto sel = Get(sei);
|
||||||
Trig trig;
|
Trig trig;
|
||||||
for (auto i : Range(3))
|
for (auto i : Range(3))
|
||||||
@ -129,8 +141,8 @@ struct GrowthVectorLimiter {
|
|||||||
return trig;
|
return trig;
|
||||||
}
|
}
|
||||||
|
|
||||||
Trig GetSideTrig(SurfaceElementIndex sei, int index, double shift = 0.0,
|
Trig GetSideTrig (SurfaceElementIndex sei, int index, double shift = 0.0, bool grow_first_vertex = true)
|
||||||
bool grow_first_vertex = true) {
|
{
|
||||||
auto trig = GetMappedTrig(sei, 0.0);
|
auto trig = GetMappedTrig(sei, 0.0);
|
||||||
auto sel = Get(sei);
|
auto sel = Get(sei);
|
||||||
auto index1 = (index + 1) % 3;
|
auto index1 = (index + 1) % 3;
|
||||||
@ -141,23 +153,24 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static constexpr double INTERSECTION_SAFETY = .9;
|
static constexpr double INTERSECTION_SAFETY = .9;
|
||||||
bool LimitGrowthVector(PointIndex pi_to, SurfaceElementIndex sei,
|
bool LimitGrowthVector (PointIndex pi_to, SurfaceElementIndex sei, double trig_shift, double seg_shift, bool check_prism_sides = false)
|
||||||
double trig_shift, double seg_shift,
|
{
|
||||||
bool check_prism_sides = false) {
|
|
||||||
auto pi_from = map_from[pi_to];
|
auto pi_from = map_from[pi_to];
|
||||||
if (!pi_from.IsValid())
|
if (!pi_from.IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto seg = GetSeg(pi_to, seg_shift, true);
|
auto seg = GetSeg(pi_to, seg_shift, true);
|
||||||
|
|
||||||
for (auto pi : Get(sei).PNums()) {
|
for (auto pi : Get(sei).PNums())
|
||||||
|
{
|
||||||
if (pi == pi_from)
|
if (pi == pi_from)
|
||||||
return false;
|
return false;
|
||||||
if (map_from[pi] == pi_from)
|
if (map_from[pi] == pi_from)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_prism_sides || trig_shift > .0) {
|
if (check_prism_sides || trig_shift > .0)
|
||||||
|
{
|
||||||
auto [trig_min_limit, trig_max_limit] = GetMinMaxLimit(sei);
|
auto [trig_min_limit, trig_max_limit] = GetMinMaxLimit(sei);
|
||||||
if (GetLimit(pi_to) < trig_min_limit)
|
if (GetLimit(pi_to) < trig_min_limit)
|
||||||
return false;
|
return false;
|
||||||
@ -173,7 +186,8 @@ struct GrowthVectorLimiter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
double scaling = 1.0;
|
double scaling = 1.0;
|
||||||
while (true) {
|
while (true)
|
||||||
|
{
|
||||||
bool have_intersection = false;
|
bool have_intersection = false;
|
||||||
auto seg = GetSeg(pi_to, scaling * seg_shift, true);
|
auto seg = GetSeg(pi_to, scaling * seg_shift, true);
|
||||||
for (auto trig : getTrigs(scaling))
|
for (auto trig : getTrigs(scaling))
|
||||||
@ -190,12 +204,15 @@ struct GrowthVectorLimiter {
|
|||||||
for (auto pi : Get(sei).PNums())
|
for (auto pi : Get(sei).PNums())
|
||||||
SetLimit(pi, new_limit);
|
SetLimit(pi, new_limit);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
auto trig = GetTrig(sei, 0.0);
|
auto trig = GetTrig(sei, 0.0);
|
||||||
auto intersection = isIntersectingTrig(seg, trig);
|
auto intersection = isIntersectingTrig(seg, trig);
|
||||||
// checking with original surface elements -> allow only half the distance
|
// checking with original surface elements -> allow only half the distance
|
||||||
auto new_seg_limit = 0.40 * intersection.lam0 * seg_shift;
|
auto new_seg_limit = 0.40 * intersection.lam0 * seg_shift;
|
||||||
if (intersection && new_seg_limit < GetLimit(pi_from)) {
|
if (intersection && new_seg_limit < GetLimit(pi_from))
|
||||||
|
{
|
||||||
auto p0 = seg[0];
|
auto p0 = seg[0];
|
||||||
auto p1 = seg[1];
|
auto p1 = seg[1];
|
||||||
auto d = Dist(p0, p1);
|
auto d = Dist(p0, p1);
|
||||||
@ -206,20 +223,23 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EqualizeLimits(double factor = .5) {
|
void EqualizeLimits (double factor = .5)
|
||||||
|
{
|
||||||
static Timer t("GrowthVectorLimiter::EqualizeLimits");
|
static Timer t("GrowthVectorLimiter::EqualizeLimits");
|
||||||
PrintMessage(5, "GrowthVectorLimiter - equalize limits");
|
PrintMessage(5, "GrowthVectorLimiter - equalize limits");
|
||||||
RegionTimer reg(t);
|
RegionTimer reg(t);
|
||||||
if (factor == 0.0)
|
if (factor == 0.0)
|
||||||
return;
|
return;
|
||||||
for (PointIndex pi : IntRange(tool.np, mesh.GetNP())) {
|
for (PointIndex pi : IntRange(tool.np, mesh.GetNP()))
|
||||||
|
{
|
||||||
auto pi_from = map_from[pi];
|
auto pi_from = map_from[pi];
|
||||||
std::set<PointIndex> pis;
|
std::set<PointIndex> pis;
|
||||||
for (auto sei : p2sel[pi])
|
for (auto sei : p2sel[pi])
|
||||||
for (auto pi_ : tool.new_sels[sei].PNums())
|
for (auto pi_ : tool.new_sels[sei].PNums())
|
||||||
pis.insert(pi_);
|
pis.insert(pi_);
|
||||||
ArrayMem<double, 20> limits;
|
ArrayMem<double, 20> limits;
|
||||||
for (auto pi1 : pis) {
|
for (auto pi1 : pis)
|
||||||
|
{
|
||||||
auto limit = GetLimit(pi1);
|
auto limit = GetLimit(pi1);
|
||||||
if (limit > 0.0)
|
if (limit > 0.0)
|
||||||
limits.Append(GetLimit(pi1));
|
limits.Append(GetLimit(pi1));
|
||||||
@ -231,7 +251,8 @@ struct GrowthVectorLimiter {
|
|||||||
double mean_limit = limits[limits.Size() / 2];
|
double mean_limit = limits[limits.Size() / 2];
|
||||||
// if mean limit is the maximum limit, take the average of second-highest
|
// if mean limit is the maximum limit, take the average of second-highest
|
||||||
// and highest value
|
// and highest value
|
||||||
if (mean_limit > limits[0] && mean_limit == limits.Last()) {
|
if (mean_limit > limits[0] && mean_limit == limits.Last())
|
||||||
|
{
|
||||||
auto i = limits.Size() - 1;
|
auto i = limits.Size() - 1;
|
||||||
while (limits[i] == limits.Last())
|
while (limits[i] == limits.Last())
|
||||||
i--;
|
i--;
|
||||||
@ -245,7 +266,8 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitSelfIntersection(double safety = 1.4) {
|
void LimitSelfIntersection (double safety = 1.4)
|
||||||
|
{
|
||||||
static Timer t("GrowthVectorLimiter::LimitSelfIntersection");
|
static Timer t("GrowthVectorLimiter::LimitSelfIntersection");
|
||||||
PrintMessage(5, "GrowthVectorLimiter - self intersection");
|
PrintMessage(5, "GrowthVectorLimiter - self intersection");
|
||||||
RegionTimer reg(t);
|
RegionTimer reg(t);
|
||||||
@ -260,16 +282,20 @@ struct GrowthVectorLimiter {
|
|||||||
return false;
|
return false;
|
||||||
const auto sel = Get(sei);
|
const auto sel = Get(sei);
|
||||||
auto np = sel.GetNP();
|
auto np = sel.GetNP();
|
||||||
for (auto i : Range(np)) {
|
for (auto i : Range(np))
|
||||||
|
{
|
||||||
if (sel[i] > tool.np)
|
if (sel[i] > tool.np)
|
||||||
return false;
|
return false;
|
||||||
if (tool.mapto[sel[i]].Size() == 0)
|
if (tool.mapto[sel[i]].Size() == 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (auto i : Range(np)) {
|
for (auto i : Range(np))
|
||||||
|
{
|
||||||
auto seg = GetMappedSeg(sel[i], shift * limits[sel[i]]);
|
auto seg = GetMappedSeg(sel[i], shift * limits[sel[i]]);
|
||||||
for (auto fi : Range(np - 2)) {
|
for (auto fi : Range(np - 2))
|
||||||
for (auto side : {true, false}) {
|
{
|
||||||
|
for (auto side : {true, false})
|
||||||
|
{
|
||||||
auto trig = GetSideTrig(sei, i + fi, 1.0, side);
|
auto trig = GetSideTrig(sei, i + fi, 1.0, side);
|
||||||
if (isIntersectingPlane(seg, trig))
|
if (isIntersectingPlane(seg, trig))
|
||||||
return true;
|
return true;
|
||||||
@ -279,7 +305,8 @@ struct GrowthVectorLimiter {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
for (SurfaceElementIndex sei : mesh.SurfaceElements().Range()) {
|
for (SurfaceElementIndex sei : mesh.SurfaceElements().Range())
|
||||||
|
{
|
||||||
auto sel = mesh[sei];
|
auto sel = mesh[sei];
|
||||||
const auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());
|
const auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());
|
||||||
if (sel.GetNP() == 4)
|
if (sel.GetNP() == 4)
|
||||||
@ -289,7 +316,8 @@ struct GrowthVectorLimiter {
|
|||||||
|
|
||||||
double shift = 1.0;
|
double shift = 1.0;
|
||||||
const double step_factor = 0.9;
|
const double step_factor = 0.9;
|
||||||
while (isIntersecting(sei, shift * safety)) {
|
while (isIntersecting(sei, shift * safety))
|
||||||
|
{
|
||||||
shift *= step_factor;
|
shift *= step_factor;
|
||||||
double max_limit = 0;
|
double max_limit = 0;
|
||||||
for (auto i : Range(np))
|
for (auto i : Range(np))
|
||||||
@ -305,7 +333,8 @@ struct GrowthVectorLimiter {
|
|||||||
// checks if a segment is intersecting a plane, spanned by three points, lam
|
// checks if a segment is intersecting a plane, spanned by three points, lam
|
||||||
// will be set s.t. p_intersect = seg[0] + lam * (seg[1]-seg[0])
|
// will be set s.t. p_intersect = seg[0] + lam * (seg[1]-seg[0])
|
||||||
Intersection_ isIntersectingPlane (const Seg& seg,
|
Intersection_ isIntersectingPlane (const Seg& seg,
|
||||||
const Trig & trig) {
|
const Trig& trig)
|
||||||
|
{
|
||||||
auto t1 = trig[1] - trig[0];
|
auto t1 = trig[1] - trig[0];
|
||||||
auto t2 = trig[2] - trig[0];
|
auto t2 = trig[2] - trig[0];
|
||||||
auto n = Cross(t1, t2);
|
auto n = Cross(t1, t2);
|
||||||
@ -315,14 +344,13 @@ struct GrowthVectorLimiter {
|
|||||||
Intersection_ intersection;
|
Intersection_ intersection;
|
||||||
intersection.lam0 = -v0n / (v1n - v0n);
|
intersection.lam0 = -v0n / (v1n - v0n);
|
||||||
intersection.p = seg[0] + intersection.lam0 * (seg[1] - seg[0]);
|
intersection.p = seg[0] + intersection.lam0 * (seg[1] - seg[0]);
|
||||||
intersection.is_intersecting = (v0n * v1n < 0) &&
|
intersection.is_intersecting = (v0n * v1n < 0) && (intersection.lam0 > -1e-8) && (intersection.lam0 < 1 + 1e-8);
|
||||||
(intersection.lam0 > -1e-8) &&
|
|
||||||
(intersection.lam0 < 1 + 1e-8);
|
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_ isIntersectingTrig(const Seg &seg, const Trig &trig) {
|
Intersection_ isIntersectingTrig (const Seg& seg, const Trig& trig)
|
||||||
|
{
|
||||||
auto intersection = isIntersectingPlane(seg, trig);
|
auto intersection = isIntersectingPlane(seg, trig);
|
||||||
if (!intersection)
|
if (!intersection)
|
||||||
return intersection;
|
return intersection;
|
||||||
@ -338,39 +366,43 @@ struct GrowthVectorLimiter {
|
|||||||
|
|
||||||
intersection.lam1 = 0;
|
intersection.lam1 = 0;
|
||||||
double eps = 0.1;
|
double eps = 0.1;
|
||||||
if (bary.X() >= -eps && bary.Y() >= -eps &&
|
if (bary.X() >= -eps && bary.Y() >= -eps && bary.X() + bary.Y() <= 1 + eps)
|
||||||
bary.X() + bary.Y() <= 1 + eps) {
|
{
|
||||||
intersection.bary[0] = bary.X();
|
intersection.bary[0] = bary.X();
|
||||||
intersection.bary[1] = bary.Y();
|
intersection.bary[1] = bary.Y();
|
||||||
intersection.bary[2] = 1.0 - bary.X() - bary.Y();
|
intersection.bary[2] = 1.0 - bary.X() - bary.Y();
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
intersection.is_intersecting = false;
|
intersection.is_intersecting = false;
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_ isIntersectingTrig(PointIndex pi_from, PointIndex pi_to,
|
Intersection_ isIntersectingTrig (PointIndex pi_from, PointIndex pi_to, SurfaceElementIndex sei, double shift = 0.0)
|
||||||
SurfaceElementIndex sei,
|
{
|
||||||
double shift = 0.0) {
|
|
||||||
return isIntersectingTrig(GetSeg(pi_from, pi_to), GetTrig(sei, shift));
|
return isIntersectingTrig(GetSeg(pi_from, pi_to), GetTrig(sei, shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildSearchTree(double trig_shift) {
|
void BuildSearchTree (double trig_shift)
|
||||||
|
{
|
||||||
static Timer t("BuildSearchTree");
|
static Timer t("BuildSearchTree");
|
||||||
RegionTimer rt(t);
|
RegionTimer rt(t);
|
||||||
Box<3> bbox(Box<3>::EMPTY_BOX);
|
Box<3> bbox(Box<3>::EMPTY_BOX);
|
||||||
for (PointIndex pi : mesh.Points().Range()) {
|
for (PointIndex pi : mesh.Points().Range())
|
||||||
|
{
|
||||||
bbox.Add(mesh[pi]);
|
bbox.Add(mesh[pi]);
|
||||||
bbox.Add(GetPoint(pi, 1.1));
|
bbox.Add(GetPoint(pi, 1.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
tree = make_unique<BoxTree<3>>(bbox);
|
tree = make_unique<BoxTree<3>>(bbox);
|
||||||
|
|
||||||
for (auto sei : SurfaceElementsRange()) {
|
for (auto sei : SurfaceElementsRange())
|
||||||
|
{
|
||||||
const auto& sel = Get(sei);
|
const auto& sel = Get(sei);
|
||||||
auto sel_index = sel.GetIndex();
|
auto sel_index = sel.GetIndex();
|
||||||
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
for (auto pi : sel.PNums()) {
|
for (auto pi : sel.PNums())
|
||||||
|
{
|
||||||
box.Add(GetPoint(pi, 0.));
|
box.Add(GetPoint(pi, 0.));
|
||||||
box.Add(GetPoint(pi, trig_shift * GetLimit(pi)));
|
box.Add(GetPoint(pi, trig_shift * GetLimit(pi)));
|
||||||
}
|
}
|
||||||
@ -379,21 +411,21 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TFunc>
|
template <typename TFunc>
|
||||||
void FindTreeIntersections(double trig_shift, double seg_shift, TFunc f,
|
void FindTreeIntersections (double trig_shift, double seg_shift, TFunc f, BitArray* relevant_points = nullptr)
|
||||||
BitArray *relevant_points = nullptr) {
|
{
|
||||||
static Timer t("GrowthVectorLimiter::FindTreeIntersections");
|
static Timer t("GrowthVectorLimiter::FindTreeIntersections");
|
||||||
RegionTimer rt(t);
|
RegionTimer rt(t);
|
||||||
BuildSearchTree(trig_shift);
|
BuildSearchTree(trig_shift);
|
||||||
auto np_new = mesh.Points().Size();
|
auto np_new = mesh.Points().Size();
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (auto i : IntRange(tool.np, np_new)) {
|
for (auto i : IntRange(tool.np, np_new))
|
||||||
|
{
|
||||||
PointIndex pi_to = i + PointIndex::BASE;
|
PointIndex pi_to = i + PointIndex::BASE;
|
||||||
PointIndex pi_from = map_from[pi_to];
|
PointIndex pi_from = map_from[pi_to];
|
||||||
if (!pi_from.IsValid())
|
if (!pi_from.IsValid())
|
||||||
throw Exception("Point not mapped");
|
throw Exception("Point not mapped");
|
||||||
|
|
||||||
if (relevant_points && !relevant_points->Test(pi_to) &&
|
if (relevant_points && !relevant_points->Test(pi_to) && !relevant_points->Test(pi_from))
|
||||||
!relevant_points->Test(pi_from))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
@ -401,8 +433,7 @@ struct GrowthVectorLimiter {
|
|||||||
|
|
||||||
box.Add(GetPoint(pi_to, 0));
|
box.Add(GetPoint(pi_to, 0));
|
||||||
box.Add(GetPoint(pi_to, GetLimit(pi_from)));
|
box.Add(GetPoint(pi_to, GetLimit(pi_from)));
|
||||||
tree->GetFirstIntersecting(box.PMin(), box.PMax(),
|
tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&] (SurfaceElementIndex sei) {
|
||||||
[&](SurfaceElementIndex sei) {
|
|
||||||
const auto& sel = Get(sei);
|
const auto& sel = Get(sei);
|
||||||
if (sel.PNums().Contains(pi_from))
|
if (sel.PNums().Contains(pi_from))
|
||||||
return false;
|
return false;
|
||||||
@ -415,18 +446,21 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixIntersectingSurfaceTrigs() {
|
void FixIntersectingSurfaceTrigs ()
|
||||||
|
{
|
||||||
static Timer t("GrowthVectorLimiter::FixIntersectingSurfaceTrigs");
|
static Timer t("GrowthVectorLimiter::FixIntersectingSurfaceTrigs");
|
||||||
RegionTimer reg(t);
|
RegionTimer reg(t);
|
||||||
// check if surface trigs are intersecting each other
|
// check if surface trigs are intersecting each other
|
||||||
bool changed = true;
|
bool changed = true;
|
||||||
while (changed) {
|
while (changed)
|
||||||
|
{
|
||||||
changed = false;
|
changed = false;
|
||||||
Point3d pmin, pmax;
|
Point3d pmin, pmax;
|
||||||
mesh.GetBox(pmin, pmax);
|
mesh.GetBox(pmin, pmax);
|
||||||
BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);
|
BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);
|
||||||
|
|
||||||
for (auto sei : SurfaceElementsRange()) {
|
for (auto sei : SurfaceElementsRange())
|
||||||
|
{
|
||||||
const Element2d& tri = Get(sei);
|
const Element2d& tri = Get(sei);
|
||||||
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
@ -437,7 +471,8 @@ struct GrowthVectorLimiter {
|
|||||||
setree.Insert(box, sei);
|
setree.Insert(box, sei);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto sei : SurfaceElementsRange()) {
|
for (auto sei : SurfaceElementsRange())
|
||||||
|
{
|
||||||
const Element2d& tri = Get(sei);
|
const Element2d& tri = Get(sei);
|
||||||
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
@ -452,12 +487,14 @@ struct GrowthVectorLimiter {
|
|||||||
|
|
||||||
netgen::Point<3> tri1_points[3], tri2_points[3];
|
netgen::Point<3> tri1_points[3], tri2_points[3];
|
||||||
const netgen::Point<3>*trip1[3], *trip2[3];
|
const netgen::Point<3>*trip1[3], *trip2[3];
|
||||||
for (int k = 0; k < 3; k++) {
|
for (int k = 0; k < 3; k++)
|
||||||
|
{
|
||||||
trip1[k] = &tri1_points[k];
|
trip1[k] = &tri1_points[k];
|
||||||
trip2[k] = &tri2_points[k];
|
trip2[k] = &tri2_points[k];
|
||||||
}
|
}
|
||||||
auto set_points = [&] () {
|
auto set_points = [&] () {
|
||||||
for (int k = 0; k < 3; k++) {
|
for (int k = 0; k < 3; k++)
|
||||||
|
{
|
||||||
tri1_points[k] = GetPoint(tri[k], 1.0, true);
|
tri1_points[k] = GetPoint(tri[k], 1.0, true);
|
||||||
tri2_points[k] = GetPoint(tri2[k], 1.0, true);
|
tri2_points[k] = GetPoint(tri2[k], 1.0, true);
|
||||||
}
|
}
|
||||||
@ -466,13 +503,13 @@ struct GrowthVectorLimiter {
|
|||||||
set_points();
|
set_points();
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while (IntersectTriangleTriangle(&trip1[0], &trip2[0])) {
|
while (IntersectTriangleTriangle(&trip1[0], &trip2[0]))
|
||||||
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
PointIndex pi_max_limit = PointIndex::INVALID;
|
PointIndex pi_max_limit = PointIndex::INVALID;
|
||||||
for (PointIndex pi :
|
for (PointIndex pi :
|
||||||
{tri[0], tri[1], tri[2], tri2[0], tri2[1], tri2[2]})
|
{tri[0], tri[1], tri[2], tri2[0], tri2[1], tri2[2]})
|
||||||
if (pi > tool.np && (!pi_max_limit.IsValid() ||
|
if (pi > tool.np && (!pi_max_limit.IsValid() || GetLimit(pi) > GetLimit(pi_max_limit)))
|
||||||
GetLimit(pi) > GetLimit(pi_max_limit)))
|
|
||||||
pi_max_limit = map_from[pi];
|
pi_max_limit = map_from[pi];
|
||||||
|
|
||||||
if (!pi_max_limit.IsValid())
|
if (!pi_max_limit.IsValid())
|
||||||
@ -481,11 +518,13 @@ struct GrowthVectorLimiter {
|
|||||||
ScaleLimit(pi_max_limit, 0.9);
|
ScaleLimit(pi_max_limit, 0.9);
|
||||||
set_points();
|
set_points();
|
||||||
counter++;
|
counter++;
|
||||||
if (counter > 20) {
|
if (counter > 20)
|
||||||
|
{
|
||||||
cerr << "Limit intersecting surface elements: too many "
|
cerr << "Limit intersecting surface elements: too many "
|
||||||
"limitation steps, sels: "
|
"limitation steps, sels: "
|
||||||
<< Get(sei) << '\t' << Get(sej) << endl;
|
<< Get(sei) << '\t' << Get(sej) << endl;
|
||||||
for (auto si : {sei, sej}) {
|
for (auto si : {sei, sej})
|
||||||
|
{
|
||||||
auto sel = Get(si);
|
auto sel = Get(si);
|
||||||
cerr << "Limits: ";
|
cerr << "Limits: ";
|
||||||
for (auto pi : sel.PNums())
|
for (auto pi : sel.PNums())
|
||||||
@ -505,7 +544,8 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitOriginalSurface(double safety) {
|
void LimitOriginalSurface (double safety)
|
||||||
|
{
|
||||||
static Timer t("GrowthVectorLimiter::LimitOriginalSurface");
|
static Timer t("GrowthVectorLimiter::LimitOriginalSurface");
|
||||||
RegionTimer reg(t);
|
RegionTimer reg(t);
|
||||||
PrintMessage(5, "GrowthVectorLimiter - original surface");
|
PrintMessage(5, "GrowthVectorLimiter - original surface");
|
||||||
@ -520,7 +560,8 @@ struct GrowthVectorLimiter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LimitBoundaryLayer(double safety = 1.1) {
|
void LimitBoundaryLayer (double safety = 1.1)
|
||||||
|
{
|
||||||
static Timer t("GrowthVectorLimiter::LimitBoundaryLayer");
|
static Timer t("GrowthVectorLimiter::LimitBoundaryLayer");
|
||||||
PrintMessage(5, "GrowthVectorLimiter - boundary layer");
|
PrintMessage(5, "GrowthVectorLimiter - boundary layer");
|
||||||
// now limit again with shifted surface elements
|
// now limit again with shifted surface elements
|
||||||
@ -533,22 +574,24 @@ struct GrowthVectorLimiter {
|
|||||||
relevant_points_next.SetSize(mesh.Points().Size() + 1);
|
relevant_points_next.SetSize(mesh.Points().Size() + 1);
|
||||||
relevant_points.Set();
|
relevant_points.Set();
|
||||||
|
|
||||||
while (limit_counter) {
|
while (limit_counter)
|
||||||
|
{
|
||||||
RegionTimer reg(t);
|
RegionTimer reg(t);
|
||||||
size_t find_counter = 0;
|
size_t find_counter = 0;
|
||||||
limit_counter = 0;
|
limit_counter = 0;
|
||||||
relevant_points_next.Clear();
|
relevant_points_next.Clear();
|
||||||
FindTreeIntersections(
|
FindTreeIntersections(
|
||||||
trig_shift, seg_shift,
|
trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {
|
||||||
[&](PointIndex pi_to, SurfaceElementIndex sei) {
|
|
||||||
find_counter++;
|
find_counter++;
|
||||||
auto sel = Get(sei);
|
auto sel = Get(sei);
|
||||||
|
|
||||||
if (LimitGrowthVector(pi_to, sei, trig_shift, seg_shift)) {
|
if (LimitGrowthVector(pi_to, sei, trig_shift, seg_shift))
|
||||||
|
{
|
||||||
limit_counter++;
|
limit_counter++;
|
||||||
relevant_points_next.SetBit(pi_to);
|
relevant_points_next.SetBit(pi_to);
|
||||||
relevant_points_next.SetBit(map_from[pi_to]);
|
relevant_points_next.SetBit(map_from[pi_to]);
|
||||||
for (auto pi : sel.PNums()) {
|
for (auto pi : sel.PNums())
|
||||||
|
{
|
||||||
relevant_points_next.SetBit(pi);
|
relevant_points_next.SetBit(pi);
|
||||||
if (pi >= tool.np)
|
if (pi >= tool.np)
|
||||||
relevant_points_next.SetBit(map_from[pi]);
|
relevant_points_next.SetBit(map_from[pi]);
|
||||||
@ -557,7 +600,8 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto pi : sel.PNums()) {
|
for (auto pi : sel.PNums())
|
||||||
|
{
|
||||||
if (pi >= tool.np)
|
if (pi >= tool.np)
|
||||||
return;
|
return;
|
||||||
if (tool.mapto[pi].Size() == 0)
|
if (tool.mapto[pi].Size() == 0)
|
||||||
@ -571,7 +615,8 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perform() {
|
void Perform ()
|
||||||
|
{
|
||||||
limits.SetSize(mesh.Points().Size());
|
limits.SetSize(mesh.Points().Size());
|
||||||
limits = 1.0;
|
limits = 1.0;
|
||||||
|
|
||||||
@ -580,7 +625,8 @@ struct GrowthVectorLimiter {
|
|||||||
// No smoothing in the last pass, to avoid generating new intersections
|
// No smoothing in the last pass, to avoid generating new intersections
|
||||||
std::array smoothing_factors = {0.8, 0.7, 0.5, 0.0};
|
std::array smoothing_factors = {0.8, 0.7, 0.5, 0.0};
|
||||||
|
|
||||||
for (auto i_pass : Range(safeties.size())) {
|
for (auto i_pass : Range(safeties.size()))
|
||||||
|
{
|
||||||
PrintMessage(4, "GrowthVectorLimiter pass ", i_pass);
|
PrintMessage(4, "GrowthVectorLimiter pass ", i_pass);
|
||||||
double safety = safeties[i_pass];
|
double safety = safeties[i_pass];
|
||||||
// intersect segment with original surface elements
|
// intersect segment with original surface elements
|
||||||
@ -600,8 +646,10 @@ struct GrowthVectorLimiter {
|
|||||||
for (auto i : Range(growthvectors))
|
for (auto i : Range(growthvectors))
|
||||||
growthvectors[i] *= limits[i];
|
growthvectors[i] *= limits[i];
|
||||||
|
|
||||||
for (auto &[special_pi, special_point] : tool.special_boundary_points) {
|
for (auto& [special_pi, special_point] : tool.special_boundary_points)
|
||||||
for (auto &group : special_point.growth_groups) {
|
{
|
||||||
|
for (auto& group : special_point.growth_groups)
|
||||||
|
{
|
||||||
group.growth_vector *= limits[special_pi];
|
group.growth_vector *= limits[special_pi];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user