Free edges - split Segments if other optimizations are not enough, also apply ImproveMesh

This commit is contained in:
Matthias Hochsteger 2025-02-14 10:04:56 +01:00
parent 15ffcbae8e
commit 058cdce84d

View File

@ -777,18 +777,16 @@ namespace netgen
if(geo->GetSolid(domain-1).free_edges.Size() == 0) if(geo->GetSolid(domain-1).free_edges.Size() == 0)
return; return;
Segment bad_seg; Array<SegmentIndex> free_segs;
Array<Segment> free_segs; for (auto segi : Range(mesh.LineSegments()))
for (auto seg : mesh.LineSegments()) if(mesh[segi].domin == domain && mesh[segi].domout == domain)
if(seg.domin == domain && seg.domout == domain) free_segs.Append(segi);
free_segs.Append(seg);
auto num_nonconforming = [&] () { auto get_nonconforming = [&] (const auto & p2el) {
size_t count = 0; Array<size_t> nonconforming;
auto p2el = mesh.CreatePoint2ElementTable(); for (auto segi : free_segs) {
auto seg = mesh[segi];
for (auto seg : free_segs) {
auto has_p0 = p2el[seg[0]]; auto has_p0 = p2el[seg[0]];
bool has_both = false; bool has_both = false;
@ -798,34 +796,106 @@ namespace netgen
has_both = true; has_both = true;
} }
if(!has_both) { if(!has_both)
bad_seg = seg; nonconforming.Append(segi);
count++;
}
} }
return count; return nonconforming;
}; };
for ([[maybe_unused]] auto i : Range(5)) { auto split_segment = [&] (SegmentIndex segi, const auto & p2el) {
auto num_bad_segs = num_nonconforming(); // Todo: handle curved segments correctly
PrintMessage(1, "Non-conforming free segments in domain ", domain, ": ", num_bad_segs); auto seg = mesh[segi];
auto p_new = Center(mesh[seg[0]], mesh[seg[1]]);
auto pi_new = mesh.AddPoint(p_new);
auto seg_new0 = seg;
auto seg_new1 = seg;
seg_new0[1] = pi_new;
seg_new1[0] = pi_new;
mesh[segi][0] = PointIndex::INVALID;
mesh.AddSegment(seg_new0);
mesh.AddSegment(seg_new1);
double lam[3];
ElementIndex ei = mesh.GetElementOfPoint(p_new, lam, false, domain);
if(ei == 0) {
PrintMessage(1, "Could not find volume element with new point");
return;
}
ei -= 1;
// split tet into 4 new tests, with new point inside
auto el = mesh[ei];
if(el.GetNP() != 4) {
PrintMessage(1, "Only tet elements are supported to split around free segments");
return;
}
if(el.IsDeleted()) {
PrintMessage(1,"Element to split is already deleted");
return;
}
int pmap[4][4] = {
{0,1,2,4},
{1,3,2,4},
{0,2,3,4},
{0,3,1,4}
};
PointIndex pis[5] = {el[0], el[1], el[2], el[3], pi_new};
for (auto i : Range(4)) {
Element el_new;
el_new = el;
for (auto j : Range(4))
el_new[j] = pis[pmap[i][j]];
mesh.AddVolumeElement(el_new);
}
mesh[ei].Delete();
};
size_t last_num_bad_segs = -1;
for ([[maybe_unused]] auto i : Range(10)) {
auto p2el = mesh.CreatePoint2ElementTable();
auto bad_segs = get_nonconforming(p2el);
auto num_bad_segs = bad_segs.Size();
if(num_bad_segs == 0) if(num_bad_segs == 0)
return; return;
PrintMessage(3, "Non-conforming free segments in domain ", domain, ": ", num_bad_segs);
if(i>=5 || num_bad_segs != last_num_bad_segs) {
for(auto i : bad_segs)
split_segment(i, p2el);
mesh.Compress();
}
MeshingParameters dummymp; MeshingParameters dummymp;
MeshOptimize3d optmesh(mesh, dummymp, OPT_CONFORM); MeshOptimize3d optmesh(mesh, dummymp, OPT_CONFORM);
for ([[maybe_unused]] auto i : Range(3)) { for ([[maybe_unused]] auto i : Range(3)) {
optmesh.ImproveMesh();
optmesh.SwapImprove2 (); optmesh.SwapImprove2 ();
optmesh.ImproveMesh();
optmesh.SwapImprove(); optmesh.SwapImprove();
optmesh.ImproveMesh();
optmesh.CombineImprove(); optmesh.CombineImprove();
} }
last_num_bad_segs = num_bad_segs;
} }
if(debugparam.write_mesh_on_error) auto p2el = mesh.CreatePoint2ElementTable();
mesh.Save("free_segment_not_conformed_dom_"+ToString(domain)+"_seg_"+ToString(bad_seg[0])+"_"+ToString(bad_seg[1])+".vol.gz"); auto bad_segs = get_nonconforming(p2el);
throw Exception("Segment not resolved in volume mesh in domain " + ToString(domain)+ ", seg: " + ToString(bad_seg));
if(bad_segs.Size() > 0) {
auto bad_seg = mesh[free_segs[bad_segs[0]]];
if(debugparam.write_mesh_on_error)
mesh.Save("free_segment_not_conformed_dom_"+ToString(domain)+"_seg_"+ToString(bad_seg[0])+"_"+ToString(bad_seg[1])+".vol.gz");
throw Exception("Segment not resolved in volume mesh in domain " + ToString(domain)+ ", seg: " + ToString(bad_seg));
}
} }