mirror of
https://github.com/NGSolve/netgen.git
synced 2025-01-19 09:20:33 +05:00
Fixes in growth vector limitation
This commit is contained in:
parent
e30b727c7b
commit
e7b5eabdc3
@ -148,37 +148,56 @@ struct GrowthVectorLimiter {
|
|||||||
FlatArray<Vec<3>, PointIndex> growthvectors;
|
FlatArray<Vec<3>, PointIndex> growthvectors;
|
||||||
BitArray changed_domains;
|
BitArray changed_domains;
|
||||||
unique_ptr<BoxTree<3>> tree;
|
unique_ptr<BoxTree<3>> tree;
|
||||||
|
Array<PointIndex, PointIndex> map_from;
|
||||||
ofstream debug;
|
ofstream debug;
|
||||||
|
|
||||||
GrowthVectorLimiter( BoundaryLayerTool & tool_, Mesh & mesh_, const BoundaryLayerParameters & params_, FlatArray<double, PointIndex> limits_, FlatArray<Vec<3>, PointIndex> growthvectors_, double height_) :
|
GrowthVectorLimiter( BoundaryLayerTool & tool_, Mesh & mesh_, const BoundaryLayerParameters & params_, FlatArray<double, PointIndex> limits_, FlatArray<Vec<3>, PointIndex> growthvectors_, double height_) :
|
||||||
tool(tool_),
|
tool(tool_),
|
||||||
params(params_), mesh(mesh_), height(height_), limits(limits_), growthvectors(growthvectors_), debug("debug.txt") {
|
params(params_), mesh(mesh_), height(height_), limits(limits_), growthvectors(growthvectors_), map_from(mesh.Points().Size()), debug("debug.txt") {
|
||||||
changed_domains = params.domains;
|
changed_domains = params.domains;
|
||||||
if(!params.outside)
|
if(!params.outside)
|
||||||
changed_domains.Invert();
|
changed_domains.Invert();
|
||||||
|
|
||||||
|
map_from = PointIndex::INVALID;
|
||||||
|
for(auto pi : tool.mapto.Range())
|
||||||
|
for (auto pi_to : tool.mapto[pi])
|
||||||
|
map_from[pi_to] = pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
Face GetFace( SurfaceElementIndex sei );
|
Face GetFace( SurfaceElementIndex sei );
|
||||||
Face GetMappedFace( SurfaceElementIndex sei );
|
Face GetMappedFace( SurfaceElementIndex sei );
|
||||||
Face GetMappedFace( SurfaceElementIndex sei, int face );
|
Face GetMappedFace( SurfaceElementIndex sei, int face );
|
||||||
|
|
||||||
auto GetSeg(PointIndex pi, PointIndex pi_to, double shift=1.) {
|
Point<3> GetPoint(PointIndex pi_to, double shift=1.) {
|
||||||
return std::array<Point<3>, 2>{mesh[pi], mesh[pi]+shift*(mesh[pi_to]-mesh[pi])};
|
if(shift == 1.) return mesh[pi_to];
|
||||||
|
auto pi_from = map_from[pi_to];
|
||||||
|
if(!pi_from.IsValid()) return mesh[pi_to];
|
||||||
|
if(shift == 0.) return mesh[pi_from];
|
||||||
|
Point<3> p_from = mesh[pi_from];
|
||||||
|
auto [gw_ptr, h] = tool.growth_vector_map.at(pi_to);
|
||||||
|
Point<3> p_to = mesh[pi_to] + h * limits[pi_to] * (*gw_ptr);
|
||||||
|
return p_from + shift * (p_to - p_from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<Point<3>, 2> GetSeg(PointIndex pi_to, double shift=1.) {
|
||||||
|
return {GetPoint(pi_to, 0), GetPoint(pi_to, shift)};
|
||||||
|
}
|
||||||
|
|
||||||
auto GetTrig(SurfaceElementIndex sei, double shift = 0.0) {
|
auto GetTrig(SurfaceElementIndex sei, double shift = 0.0) {
|
||||||
auto sel = mesh[sei];
|
auto sel = mesh[sei];
|
||||||
auto trig = std::array<Point<3>, 3> { mesh[sel[0]], mesh[sel[1]], mesh[sel[2]] };
|
std::array<Point<3>, 3> trig;
|
||||||
if(shift)
|
|
||||||
for (auto i : Range(3))
|
for (auto i : Range(3))
|
||||||
trig[i] += height * shift * limits[sel[i]] * growthvectors[sel[i]];
|
trig[i] = mesh[sel[i]];
|
||||||
return trig;
|
return trig;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetSideTrig(SurfaceElementIndex sei, int index, double shift = 0.0) {
|
auto GetSideTrig(SurfaceElementIndex sei, int index, double shift = 0.0) {
|
||||||
auto trig = GetTrig(sei, shift);
|
auto trig = GetTrig(sei, 0.0);
|
||||||
auto sel = mesh[sei];
|
auto sel = mesh[sei];
|
||||||
auto index1 = (index+1)%3;
|
auto index1 = (index+1)%3;
|
||||||
trig[index] = trig[index1];
|
trig[index] = trig[index1];
|
||||||
trig[index] += height * shift * limits[sel[index1]] * growthvectors[sel[index1]];
|
auto [gw_ptr, h] = tool.growth_vector_map.at(sel[index1]);
|
||||||
|
trig[index] += h * shift * (*gw_ptr);
|
||||||
return trig;
|
return trig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,53 +232,47 @@ struct GrowthVectorLimiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static constexpr double INTERSECTION_SAFETY = .99;
|
static constexpr double INTERSECTION_SAFETY = .99;
|
||||||
void LimitGrowthVector(PointIndex pi, SurfaceElementIndex sei, double trig_shift, double seg_shift) {
|
void LimitGrowthVector(PointIndex pi_to, SurfaceElementIndex sei, double trig_shift, double seg_shift) {
|
||||||
Array<PointIndex> pis;
|
auto pi_from = map_from[pi_to];
|
||||||
if(tool.special_boundary_points.count(pi)) {
|
if(!pi_from.IsValid()) return;
|
||||||
for(auto & group : tool.special_boundary_points[pi].growth_groups)
|
|
||||||
pis.Append(group.new_points.Last());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pis.Append(tool.mapto[pi]);
|
|
||||||
for(auto pi_to : pis) {
|
|
||||||
if(trig_shift > 0) {
|
if(trig_shift > 0) {
|
||||||
auto intersection = isIntersectingTrig(pi, pi_to, sei, trig_shift);
|
auto intersection = isIntersectingTrig(pi_from, pi_to, sei, trig_shift);
|
||||||
if(!intersection) return;
|
if(!intersection) return;
|
||||||
double dshift = trig_shift;
|
double dshift = trig_shift;
|
||||||
while(intersection && dshift > 0.01 && dshift > intersection.lam0) {
|
while(intersection && dshift > 0.01 && dshift > intersection.lam0) {
|
||||||
dshift *= 0.9;
|
dshift *= 0.9;
|
||||||
intersection = isIntersectingTrig(pi, pi_to, sei, dshift);
|
intersection = isIntersectingTrig(pi_from, pi_to, sei, dshift);
|
||||||
}
|
}
|
||||||
dshift /= 0.9;
|
dshift /= 0.9;
|
||||||
intersection = isIntersectingTrig(pi, pi_to, sei, dshift);
|
intersection = isIntersectingTrig(pi_from, pi_to, sei, dshift);
|
||||||
if(dshift < 1)
|
if(dshift < 1)
|
||||||
cout << "final dshift " << dshift << "\t" << intersection.lam0 << endl;
|
cout << "final dshift " << dshift << "\t" << intersection.lam0 << endl;
|
||||||
limits[pi] *= intersection.lam0;
|
limits[pi_from] *= intersection.lam0;
|
||||||
auto sel = mesh[sei];
|
auto sel = mesh[sei];
|
||||||
for(auto i : Range(3))
|
for(auto i : Range(3))
|
||||||
limits[sel[i]] *= dshift;
|
limits[sel[i]] *= dshift;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto seg = GetSeg(pi, pi_to, seg_shift);
|
auto seg = GetSeg(pi_to, seg_shift);
|
||||||
auto trig = GetTrig(sei, 0.0);
|
auto trig = GetTrig(sei, 0.0);
|
||||||
// cout << mesh[sei] << " " << pi << endl;
|
// cout << mesh[sei] << " " << pi_from << endl;
|
||||||
auto intersection = isIntersectingTrig(seg, trig);
|
auto intersection = isIntersectingTrig(seg, trig);
|
||||||
auto lam = intersection.lam0;
|
auto lam = intersection.lam0;
|
||||||
// cout << "lam " << intersection.is_intersecting <<"\t" << lam << endl;
|
// cout << "lam " << intersection.is_intersecting <<"\t" << lam << endl;
|
||||||
if(intersection) {
|
if(intersection) {
|
||||||
// check with original surface elements
|
// check with original surface elements
|
||||||
limits[pi] = min(limits[pi], seg_shift*0.45*INTERSECTION_SAFETY*lam);
|
limits[pi_from] = min(limits[pi_from], seg_shift*0.45*INTERSECTION_SAFETY*lam);
|
||||||
// cout << "set limit " << pi << '\t' << limits[pi] << endl;
|
// cout << "set limit " << pi_from << '\t' << limits[pi_from] << endl;
|
||||||
if(limits[pi] < 0.1) DebugOut(pi, sei);
|
if(limits[pi_from] < 0.1) DebugOut(pi_from, sei);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// cout << "lam " << lam << endl;
|
// cout << "lam " << lam << endl;
|
||||||
// if (lam > 0 && lam < 2./INTERSECTION_SAFETY) {
|
// if (lam > 0 && lam < 2./INTERSECTION_SAFETY) {
|
||||||
// limits[pi] = min(limits[pi], 0.45*INTERSECTION_SAFETY*lam);
|
// limits[pi_from] = min(limits[pi_from], 0.45*INTERSECTION_SAFETY*lam);
|
||||||
// cout << "limit by 2 safety " << limits[pi] << endl;
|
// cout << "limit by 2 safety " << limits[pi_from] << endl;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// check with shifted surface elements using growthvectors
|
// check with shifted surface elements using growthvectors
|
||||||
// return;
|
// return;
|
||||||
@ -300,9 +313,10 @@ struct GrowthVectorLimiter {
|
|||||||
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(!changed_domains.Test(fd.DomainIn()) &&
|
if(sei < tool.nse) continue;
|
||||||
!changed_domains.Test(fd.DomainOut()))
|
// if(sei >= tool.nse || (!changed_domains.Test(fd.DomainIn()) &&
|
||||||
continue;
|
// !changed_domains.Test(fd.DomainOut())))
|
||||||
|
// continue;
|
||||||
|
|
||||||
ArrayMem<double, 4> ori_limits;
|
ArrayMem<double, 4> ori_limits;
|
||||||
ori_limits.SetSize(3);
|
ori_limits.SetSize(3);
|
||||||
@ -408,36 +422,45 @@ struct GrowthVectorLimiter {
|
|||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intersection_ isIntersectingTrig ( PointIndex pi, PointIndex pi_to, SurfaceElementIndex sei, double shift=0.0)
|
Intersection_ isIntersectingTrig ( PointIndex pi_from, PointIndex pi_to, SurfaceElementIndex sei, double shift=0.0)
|
||||||
{
|
{
|
||||||
return isIntersectingTrig(GetSeg(pi, 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) {
|
||||||
Box<3> bbox(Box<3>::EMPTY_BOX);
|
Box<3> bbox(Box<3>::EMPTY_BOX);
|
||||||
for(PointIndex pi : Range(PointIndex::BASE, PointIndex::BASE+tool.np))
|
for(PointIndex pi : mesh.Points().Range())
|
||||||
{
|
{
|
||||||
bbox.Add(mesh[pi]);
|
bbox.Add(mesh[pi]);
|
||||||
if(tool.mapto[pi].Size() >0)
|
bbox.Add(GetPoint(pi, 1.0));
|
||||||
bbox.Add(mesh[tool.mapto[pi].Last()]);
|
// 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);
|
||||||
|
|
||||||
for(auto sei : mesh.SurfaceElements().Range())
|
for(auto sei : mesh.SurfaceElements().Range())
|
||||||
{
|
{
|
||||||
|
// cout << "handle sei " << sei << ", old nse " << tool.nse << endl;
|
||||||
const auto & sel = mesh[sei];
|
const auto & sel = mesh[sei];
|
||||||
|
auto sel_index = mesh[sei].GetIndex();
|
||||||
|
// if(sel_index)
|
||||||
|
// {
|
||||||
|
// cout << "index " << sel_index << endl;
|
||||||
|
// const auto& fd = mesh.GetFaceDescriptor(sel_index);
|
||||||
|
// if( !changed_domains.Test(fd.DomainIn()) &&
|
||||||
|
// !changed_domains.Test(fd.DomainOut()))
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
Box<3> box(Box<3>::EMPTY_BOX);
|
Box<3> box(Box<3>::EMPTY_BOX);
|
||||||
const auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());
|
for(auto p : GetTrig(sei, trig_shift))
|
||||||
if(!changed_domains.Test(fd.DomainIn()) &&
|
box.Add(p);
|
||||||
!changed_domains.Test(fd.DomainOut()))
|
// for(auto pi : sel.PNums())
|
||||||
continue;
|
// box.Add(mesh[pi]);
|
||||||
for(auto pi : sel.PNums())
|
|
||||||
box.Add(mesh[pi]);
|
|
||||||
// also add moved points to bounding box
|
// also add moved points to bounding box
|
||||||
if(trig_shift >0 && params.surfid.Contains(sel.GetIndex()))
|
// for(auto p : GetTrig(sei, trig_shift))
|
||||||
for(auto pi : sel.PNums())
|
// box.Add(mesh[pi]+trig_shift*limits[pi]*height*growthvectors[pi]);
|
||||||
box.Add(mesh[pi]+trig_shift*limits[pi]*height*growthvectors[pi]);
|
|
||||||
tree->Insert(box, sei);
|
tree->Insert(box, sei);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -445,20 +468,27 @@ 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) {
|
||||||
BuildSearchTree(trig_shift);
|
BuildSearchTree(trig_shift);
|
||||||
for(auto pi : mesh.Points().Range()) {
|
auto np_new = mesh.Points().Size();
|
||||||
if(mesh[pi].Type() == INNERPOINT)
|
// cout << "np_new " << np_new << endl;
|
||||||
continue;
|
// cout << "too.np " << tool.np << endl;
|
||||||
if(growthvectors[pi].Length2() == 0.0)
|
for(auto i : IntRange(tool.np, np_new)) {
|
||||||
continue;
|
// cout << "handle point " << i << endl;
|
||||||
|
PointIndex pi_to = i+PointIndex::BASE;
|
||||||
|
// 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, seg_shift);
|
auto seg = GetSeg(pi_to, seg_shift);
|
||||||
box.Add(seg[0]);
|
box.Add(seg[0]);
|
||||||
box.Add(seg[1]);
|
box.Add(seg[1]);
|
||||||
tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&](SurfaceElementIndex sei) {
|
tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&](SurfaceElementIndex sei) {
|
||||||
const auto & sel = mesh[sei];
|
const auto & sel = mesh[sei];
|
||||||
if(sel.PNums().Contains(pi))
|
// cout << "got intersecting " << sei << endl;
|
||||||
|
auto pi_from = map_from[pi_to];
|
||||||
|
if(sel.PNums().Contains(pi_from))
|
||||||
return false;
|
return false;
|
||||||
f(pi, sei);
|
f(pi_to, sei);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -509,19 +539,22 @@ struct GrowthVectorLimiter {
|
|||||||
void BoundaryLayerTool :: LimitGrowthVectorLengths()
|
void BoundaryLayerTool :: LimitGrowthVectorLengths()
|
||||||
{
|
{
|
||||||
static Timer tall("BoundaryLayerTool::LimitGrowthVectorLengths"); RegionTimer rtall(tall);
|
static Timer tall("BoundaryLayerTool::LimitGrowthVectorLengths"); RegionTimer rtall(tall);
|
||||||
limits.SetSize(np);
|
limits.SetSize(mesh.Points().Size());
|
||||||
limits = 1.0;
|
limits = 1.0;
|
||||||
|
|
||||||
GrowthVectorLimiter limiter(*this, mesh, params, limits, growthvectors, height);
|
GrowthVectorLimiter limiter(*this, mesh, params, limits, growthvectors, height);
|
||||||
|
|
||||||
// limit to not intersect with other 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;
|
||||||
limiter.FindTreeIntersections(trig_shift, seg_shift, [&] (PointIndex pi, SurfaceElementIndex sei) {
|
limiter.FindTreeIntersections(trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {
|
||||||
limiter.LimitGrowthVector(pi, sei, trig_shift, seg_shift);
|
// cout << "found intersection 1 " << pi_to << ", " << sei << endl;
|
||||||
|
if(sei >= nse) return; // ignore new surface elements in first pass
|
||||||
|
limiter.LimitGrowthVector(pi_to, sei, trig_shift, seg_shift);
|
||||||
});
|
});
|
||||||
|
|
||||||
limiter.LimitSelfIntersection();
|
limiter.LimitSelfIntersection();
|
||||||
|
|
||||||
// for(auto i : Range(growthvectors))
|
// for(auto i : Range(growthvectors))
|
||||||
// growthvectors[i] *= limits[i];
|
// growthvectors[i] *= limits[i];
|
||||||
// limits = 1.0;
|
// limits = 1.0;
|
||||||
@ -529,15 +562,27 @@ struct GrowthVectorLimiter {
|
|||||||
// now limit again with shifted surace elements
|
// now limit again with shifted surace elements
|
||||||
trig_shift = 1.0;
|
trig_shift = 1.0;
|
||||||
seg_shift = 1.0;
|
seg_shift = 1.0;
|
||||||
limiter.FindTreeIntersections(trig_shift, seg_shift, [&] (PointIndex pi, SurfaceElementIndex sei) {
|
limiter.FindTreeIntersections(trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {
|
||||||
limiter.LimitGrowthVector(pi, sei, trig_shift, seg_shift);
|
// cout << "Should not have intersection with original surface element anymore" << endl;
|
||||||
|
// cout << "found intersection 2 " << pi_to << ", " << sei << endl;
|
||||||
|
limiter.LimitGrowthVector(pi_to, sei, trig_shift, seg_shift);
|
||||||
});
|
});
|
||||||
|
|
||||||
// for (auto i : Range(limits))
|
// for (auto i : Range(limits))
|
||||||
// if(limits[i] < 1.0)
|
// if(limits[i] < 1.0)
|
||||||
// cout << i << ": " << limits[i] << endl;
|
// cout << i << ": " << limits[i] << endl;
|
||||||
|
|
||||||
|
for (auto [pi_to, data] : growth_vector_map) {
|
||||||
|
auto pi_from = limiter.map_from[pi_to];
|
||||||
|
if(pi_from.IsValid())
|
||||||
|
limits[pi_from] = min(limits[pi_from], limits[pi_to]);
|
||||||
|
}
|
||||||
|
|
||||||
for(auto i : Range(growthvectors))
|
for(auto i : Range(growthvectors))
|
||||||
growthvectors[i] *= limits[i];
|
growthvectors[i] *= limits[i];
|
||||||
|
cout << "limits " << limits << endl;
|
||||||
|
cout << "old np " << np << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// void BoundaryLayerTool :: LimitGrowthVectorLengths()
|
// void BoundaryLayerTool :: LimitGrowthVectorLengths()
|
||||||
@ -2113,8 +2158,8 @@ struct GrowthVectorLimiter {
|
|||||||
// cout << "growthvectors before " << endl<< growthvectors << endl;
|
// cout << "growthvectors before " << endl<< growthvectors << endl;
|
||||||
// cout << "growthvectors after " << endl << growthvectors << endl;
|
// cout << "growthvectors after " << endl << growthvectors << endl;
|
||||||
|
|
||||||
// if(params.limit_growth_vectors)
|
if(params.limit_growth_vectors)
|
||||||
// LimitGrowthVectorLengths();
|
LimitGrowthVectorLengths();
|
||||||
|
|
||||||
for (auto [pi, data] : growth_vector_map) {
|
for (auto [pi, data] : growth_vector_map) {
|
||||||
auto [gw, height] = data;
|
auto [gw, height] = data;
|
||||||
|
Loading…
Reference in New Issue
Block a user