mirror of
https://github.com/NGSolve/netgen.git
synced 2025-02-22 20:15:40 +05:00
Free edges - split Segments if other optimizations are not enough, also apply ImproveMesh
This commit is contained in:
parent
15ffcbae8e
commit
058cdce84d
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user