mirror of
https://github.com/NGSolve/netgen.git
synced 2025-01-18 17:00:33 +05:00
Multiple blayer limitation passes with decreasing smothing
This commit is contained in:
parent
d82c96ba2b
commit
f6902c1f6e
@ -20,13 +20,13 @@ struct GrowthVectorLimiter {
|
|||||||
BitArray changed_domains;
|
BitArray changed_domains;
|
||||||
unique_ptr<BoxTree<3>> tree;
|
unique_ptr<BoxTree<3>> tree;
|
||||||
Array<PointIndex, PointIndex> map_from;
|
Array<PointIndex, PointIndex> map_from;
|
||||||
ofstream debug;
|
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),
|
height(tool_.total_height), growthvectors(tool_.growthvectors),
|
||||||
growthvectors(tool_.growthvectors), map_from(mesh.Points().Size()),
|
map_from(mesh.Points().Size()),
|
||||||
debug("debug.txt") {
|
p2sel(mesh.CreatePoint2SurfaceElementTable()) {
|
||||||
changed_domains = tool.domains;
|
changed_domains = tool.domains;
|
||||||
if (!params.outside)
|
if (!params.outside)
|
||||||
changed_domains.Invert();
|
changed_domains.Invert();
|
||||||
@ -53,15 +53,20 @@ struct GrowthVectorLimiter {
|
|||||||
return SetLimit(pi, limit * factor);
|
return SetLimit(pi, limit * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vec<3> GetVector(PointIndex pi_to, double shift = 1.,
|
||||||
|
bool apply_limit = false) {
|
||||||
|
auto [gw, height] = tool.growth_vector_map[pi_to];
|
||||||
|
if (apply_limit)
|
||||||
|
shift *= GetLimit(pi_to);
|
||||||
|
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 (tool.growth_vector_map.count(pi_to) == 0)
|
if (tool.growth_vector_map.count(pi_to) == 0)
|
||||||
return mesh[pi_to];
|
return mesh[pi_to];
|
||||||
|
|
||||||
auto [gw, height] = tool.growth_vector_map[pi_to];
|
return mesh[pi_to] + GetVector(pi_to, shift, apply_limit);
|
||||||
if (apply_limit)
|
|
||||||
shift *= GetLimit(pi_to);
|
|
||||||
return mesh[pi_to] + shift * height * (*gw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point<3> GetMappedPoint(PointIndex pi_from, double shift = 1.) {
|
Point<3> GetMappedPoint(PointIndex pi_from, double shift = 1.) {
|
||||||
@ -204,9 +209,33 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EqualizeLimits(double factor = .5) {
|
||||||
|
if (factor == 0.0)
|
||||||
|
return;
|
||||||
|
for (PointIndex pi : IntRange(tool.np, mesh.GetNP())) {
|
||||||
|
std::set<PointIndex> pis;
|
||||||
|
for (auto sel : p2sel[pi])
|
||||||
|
for (auto pi_ : mesh[sel].PNums())
|
||||||
|
pis.insert(pi_);
|
||||||
|
ArrayMem<double, 20> limits;
|
||||||
|
for (auto pi : pis) {
|
||||||
|
auto limit = GetLimit(pi);
|
||||||
|
if (limit > 0.0)
|
||||||
|
limits.Append(GetLimit(pi));
|
||||||
|
}
|
||||||
|
if (limits.Size() == 0)
|
||||||
|
continue;
|
||||||
|
QuickSort(limits);
|
||||||
|
double mean_limit = limits[limits.Size() / 2];
|
||||||
|
if (limits.Size() % 2 == 0)
|
||||||
|
mean_limit = 0.5 * (mean_limit + limits[(limits.Size() - 1) / 2]);
|
||||||
|
|
||||||
|
SetLimit(pi, factor * mean_limit + (1.0 - factor) * GetLimit(pi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LimitSelfIntersection() {
|
void LimitSelfIntersection() {
|
||||||
// check for self-intersection within new elements (prisms/hexes)
|
// check for self-intersection within new elements (prisms/hexes)
|
||||||
bool found_debug_element = false;
|
|
||||||
auto isIntersecting = [&](SurfaceElementIndex sei, double shift) {
|
auto isIntersecting = [&](SurfaceElementIndex sei, double shift) {
|
||||||
// checks if surface element is self intersecting when growing with factor
|
// checks if surface element is self intersecting when growing with factor
|
||||||
// shift
|
// shift
|
||||||
@ -236,23 +265,6 @@ struct GrowthVectorLimiter {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto equalizeLimits = [&](SurfaceElementIndex sei) {
|
|
||||||
const auto sel = mesh[sei];
|
|
||||||
auto np = sel.GetNP();
|
|
||||||
double max_limit = 0;
|
|
||||||
double min_limit = 1e99;
|
|
||||||
for (auto i : Range(np)) {
|
|
||||||
max_limit = max(max_limit, limits[sel[i]]);
|
|
||||||
min_limit = min(min_limit, limits[sel[i]]);
|
|
||||||
}
|
|
||||||
// equalize
|
|
||||||
if (max_limit / min_limit > 1.2) {
|
|
||||||
max_limit = min_limit * 1.2;
|
|
||||||
for (auto i : Range(np))
|
|
||||||
SetLimit(sel[i], min(limits[sel[i]], max_limit));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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());
|
||||||
@ -260,17 +272,8 @@ struct GrowthVectorLimiter {
|
|||||||
continue;
|
continue;
|
||||||
if (sel.GetNP() == 4)
|
if (sel.GetNP() == 4)
|
||||||
continue;
|
continue;
|
||||||
// if(sei >= tool.nse || (!changed_domains.Test(fd.DomainIn()) &&
|
|
||||||
// !changed_domains.Test(fd.DomainOut())))
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
auto np = sel.GetNP();
|
auto np = sel.GetNP();
|
||||||
// ArrayMem<double, 4> ori_limits;
|
|
||||||
// ori_limits.SetSize(np);
|
|
||||||
// for(auto i : Range(np))
|
|
||||||
// ori_limits[i] = limits[sel[i]];
|
|
||||||
|
|
||||||
equalizeLimits(sei);
|
|
||||||
|
|
||||||
double shift = 1.0;
|
double shift = 1.0;
|
||||||
double safety = 1.4;
|
double safety = 1.4;
|
||||||
@ -308,12 +311,6 @@ struct GrowthVectorLimiter {
|
|||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection_ isIntersectingPlane(PointIndex pi, PointIndex pi_to,
|
|
||||||
// SurfaceElementIndex sei,
|
|
||||||
// double shift = 0.0) {
|
|
||||||
// return isIntersectingPlane(GetSeg(pi, pi_to), GetTrig(sei, shift));
|
|
||||||
// }
|
|
||||||
|
|
||||||
Intersection_ isIntersectingTrig(std::array<Point<3>, 2> seg,
|
Intersection_ isIntersectingTrig(std::array<Point<3>, 2> seg,
|
||||||
std::array<Point<3>, 3> trig) {
|
std::array<Point<3>, 3> trig) {
|
||||||
auto intersection = isIntersectingPlane(seg, trig);
|
auto intersection = isIntersectingPlane(seg, trig);
|
||||||
@ -352,8 +349,6 @@ struct GrowthVectorLimiter {
|
|||||||
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));
|
||||||
// if(tool.mapto[pi].Size() >0)
|
|
||||||
// bbox.Add(mesh[tool.mapto[pi].Last()]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tree = make_unique<BoxTree<3>>(bbox);
|
tree = make_unique<BoxTree<3>>(bbox);
|
||||||
@ -382,10 +377,6 @@ struct GrowthVectorLimiter {
|
|||||||
if (!pi_from.IsValid())
|
if (!pi_from.IsValid())
|
||||||
throw Exception("Point not mapped");
|
throw Exception("Point not mapped");
|
||||||
|
|
||||||
// if(mesh[pi_to].Type() == INNERPOINT)
|
|
||||||
// continue;
|
|
||||||
// if(growthvectors[pi_to].Length2() == 0.0)
|
|
||||||
// continue;
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
auto seg = GetSeg(pi_to, seg_shift);
|
auto seg = GetSeg(pi_to, seg_shift);
|
||||||
|
|
||||||
@ -405,10 +396,80 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Perform() {
|
void FixIntersectingSurfaceTrigs() {
|
||||||
limits.SetSize(mesh.Points().Size());
|
Point3d pmin, pmax;
|
||||||
limits = 1.0;
|
mesh.GetBox(pmin, pmax);
|
||||||
|
BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);
|
||||||
|
|
||||||
|
for (auto sei : mesh.SurfaceElements().Range()) {
|
||||||
|
const Element2d &tri = mesh[sei];
|
||||||
|
|
||||||
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
|
for (PointIndex pi : tri.PNums())
|
||||||
|
box.Add(GetPoint(pi, 1.0, true));
|
||||||
|
|
||||||
|
box.Increase(1e-3 * box.Diam());
|
||||||
|
setree.Insert(box, sei);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto sei : mesh.SurfaceElements().Range()) {
|
||||||
|
const Element2d &tri = mesh[sei];
|
||||||
|
|
||||||
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
|
for (PointIndex pi : tri.PNums())
|
||||||
|
box.Add(GetPoint(pi, 1.0, true));
|
||||||
|
|
||||||
|
setree.GetFirstIntersecting(
|
||||||
|
box.PMin(), box.PMax(), [&](SurfaceElementIndex sej) {
|
||||||
|
const Element2d &tri2 = mesh[sej];
|
||||||
|
|
||||||
|
if (mesh[tri[0]].GetLayer() != mesh[tri2[0]].GetLayer())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
netgen::Point<3> tri1_points[3], tri2_points[3];
|
||||||
|
const netgen::Point<3> *trip1[3], *trip2[3];
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
trip1[k] = &tri1_points[k];
|
||||||
|
trip2[k] = &tri2_points[k];
|
||||||
|
}
|
||||||
|
auto set_points = [&]() {
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
tri1_points[k] = GetPoint(tri[k], 1.0, true);
|
||||||
|
tri2_points[k] = GetPoint(tri2[k], 1.0, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
set_points();
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
while (IntersectTriangleTriangle(&trip1[0], &trip2[0])) {
|
||||||
|
PointIndex pi_max_limit = PointIndex::INVALID;
|
||||||
|
for (PointIndex pi :
|
||||||
|
{tri[0], tri[1], tri[2], tri2[0], tri2[1], tri2[2]})
|
||||||
|
if (pi > tool.np &&
|
||||||
|
(!pi_max_limit.IsValid() ||
|
||||||
|
limits[tool.mapfrom[pi]] > limits[pi_max_limit]))
|
||||||
|
pi_max_limit = tool.mapfrom[pi];
|
||||||
|
|
||||||
|
if (!pi_max_limit.IsValid())
|
||||||
|
break;
|
||||||
|
|
||||||
|
limits[pi_max_limit] *= 0.9;
|
||||||
|
set_points();
|
||||||
|
counter++;
|
||||||
|
if (counter > 20) {
|
||||||
|
cerr << "Limit intersecting sourface elements: too many "
|
||||||
|
"limitation steps"
|
||||||
|
<< endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LimitOriginalSurface() {
|
||||||
// limit to not intersect with other (original) surface elements
|
// limit to not intersect with other (original) surface elements
|
||||||
double trig_shift = 0;
|
double trig_shift = 0;
|
||||||
double seg_shift = 2.1;
|
double seg_shift = 2.1;
|
||||||
@ -418,16 +479,12 @@ struct GrowthVectorLimiter {
|
|||||||
return; // ignore new surface elements in first pass
|
return; // ignore new surface elements in first pass
|
||||||
LimitGrowthVector(pi_to, sei, trig_shift, seg_shift);
|
LimitGrowthVector(pi_to, sei, trig_shift, seg_shift);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
LimitSelfIntersection();
|
void LimitBoundaryLayer() {
|
||||||
|
|
||||||
// for(auto i : Range(growthvectors))
|
|
||||||
// growthvectors[i] *= limits[i];
|
|
||||||
// limits = 1.0;
|
|
||||||
|
|
||||||
// now limit again with shifted surface elements
|
// now limit again with shifted surface elements
|
||||||
trig_shift = 1.1;
|
double trig_shift = 1.1;
|
||||||
seg_shift = 1.1;
|
double seg_shift = 1.1;
|
||||||
size_t limit_counter = 1;
|
size_t limit_counter = 1;
|
||||||
|
|
||||||
while (limit_counter) {
|
while (limit_counter) {
|
||||||
@ -449,78 +506,22 @@ struct GrowthVectorLimiter {
|
|||||||
limit_counter++;
|
limit_counter++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if surface trigs are intersecting each other
|
void Perform() {
|
||||||
{
|
limits.SetSize(mesh.Points().Size());
|
||||||
Point3d pmin, pmax;
|
limits = 1.0;
|
||||||
mesh.GetBox(pmin, pmax);
|
|
||||||
BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);
|
|
||||||
|
|
||||||
for (auto sei : mesh.SurfaceElements().Range()) {
|
// No smoothing in the last pass, to avoid generating new intersections
|
||||||
const Element2d &tri = mesh[sei];
|
for (auto smoothing_factor : {1.0, 0.3, 0.0}) {
|
||||||
|
LimitOriginalSurface();
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
EqualizeLimits(smoothing_factor);
|
||||||
for (PointIndex pi : tri.PNums())
|
LimitSelfIntersection();
|
||||||
box.Add(GetPoint(pi, 1.0, true));
|
EqualizeLimits(smoothing_factor);
|
||||||
|
LimitBoundaryLayer();
|
||||||
box.Increase(1e-3 * box.Diam());
|
EqualizeLimits(smoothing_factor);
|
||||||
setree.Insert(box, sei);
|
FixIntersectingSurfaceTrigs();
|
||||||
}
|
EqualizeLimits(smoothing_factor);
|
||||||
for (auto sei : mesh.SurfaceElements().Range()) {
|
|
||||||
const Element2d &tri = mesh[sei];
|
|
||||||
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
|
||||||
for (PointIndex pi : tri.PNums())
|
|
||||||
box.Add(GetPoint(pi, 1.0, true));
|
|
||||||
|
|
||||||
setree.GetFirstIntersecting(
|
|
||||||
box.PMin(), box.PMax(), [&](SurfaceElementIndex sej) {
|
|
||||||
const Element2d &tri2 = mesh[sej];
|
|
||||||
|
|
||||||
if (mesh[tri[0]].GetLayer() != mesh[tri2[0]].GetLayer())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
netgen::Point<3> tri1_points[3], tri2_points[3];
|
|
||||||
const netgen::Point<3> *trip1[3], *trip2[3];
|
|
||||||
for (int k = 0; k < 3; k++) {
|
|
||||||
trip1[k] = &tri1_points[k];
|
|
||||||
trip2[k] = &tri2_points[k];
|
|
||||||
}
|
|
||||||
auto set_points = [&]() {
|
|
||||||
for (int k = 0; k < 3; k++) {
|
|
||||||
tri1_points[k] = GetPoint(tri[k], 1.0, true);
|
|
||||||
tri2_points[k] = GetPoint(tri2[k], 1.0, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
set_points();
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
while (IntersectTriangleTriangle(&trip1[0], &trip2[0])) {
|
|
||||||
PointIndex pi_max_limit = PointIndex::INVALID;
|
|
||||||
for (PointIndex pi :
|
|
||||||
{tri[0], tri[1], tri[2], tri2[0], tri2[1], tri2[2]})
|
|
||||||
if (pi > tool.np &&
|
|
||||||
(!pi_max_limit.IsValid() ||
|
|
||||||
limits[tool.mapfrom[pi]] > limits[pi_max_limit]))
|
|
||||||
pi_max_limit = tool.mapfrom[pi];
|
|
||||||
|
|
||||||
if (!pi_max_limit.IsValid())
|
|
||||||
break;
|
|
||||||
|
|
||||||
limits[pi_max_limit] *= 0.9;
|
|
||||||
set_points();
|
|
||||||
counter++;
|
|
||||||
if (counter > 20) {
|
|
||||||
cerr << "Limit intersecting sourface elements: too many "
|
|
||||||
"limitation steps"
|
|
||||||
<< endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i : Range(growthvectors))
|
for (auto i : Range(growthvectors))
|
||||||
|
Loading…
Reference in New Issue
Block a user