Original edges retained after mesh.Refine()

Hi,

If we generate a mesh like this:

from netgen.geom2d import unit_square from ngsolve import Mesh mesh = Mesh(unit_square.GenerateMesh(maxh=.5))
The count and collection of edges returned by mesh.nedge and mesh.edges are correct:

print(mesh.nedge)

ed = {e: mesh[e].vertices for e in mesh.edges} ed
[color=green]{E0: (V0, V4), E1: (V0, V7), E2: (V1, V4), E3: (V1, V5), E4: (V2, V5), E5: (V2, V6), E6: (V3, V6),
E7: (V3, V7), E8: (V4, V5), E9: (V4, V6), E10: (V4, V7), E11: (V5, V6), E12: (V6, V7)}[/color]

If we then refine the mesh

mesh.Refine()

The count and collection of edges returned by mesh.nedge and mesh.edges are now incorrect:

print(mesh.nedge) [color=red]57[/color] (should be 44)

ed = {e: mesh[e].vertices for e in mesh.edges} ed
[color=red]{E0: (V0, V4), E1: (V0, V7), E2: (V1, V4), E3: (V1, V5), E4: (V2, V5), E5: (V2, V6), E6: (V3, V6),
E7: (V3, V7), E8: (V4, V5), E9: (V4, V6), E10: (V4, V7), E11: (V5, V6), E12: (V6, V7),[/color]
[color=green]E13: (V0, V8), E14: (V0, V13), E15: (V0, V17), E16: (V1, V9), E17: (V1, V14), E18: (V1, V18),
E19: (V2, V10), E20: (V2, V15), E21: (V2, V19), E22: (V3, V11), E23: (V3, V16), E24: (V3, V20),
E25: (V4, V8), E26: (V4, V9), E27: (V4, V12), E28: (V4, V13), E29: (V4, V18), E30: (V5, V9),
E31: (V5, V10), E32: (V5, V12), E33: (V5, V14), E34: (V5, V19), E35: (V6, V10), E36: (V6, V11),
E37: (V6, V12), E38: (V6, V15), E39: (V6, V20), E40: (V7, V8), E41: (V7, V11), E42: (V7, V12),
E43: (V7, V16), E44: (V7, V17), E45: (V8, V12), E46: (V8, V13), E47: (V8, V17), E48: (V9, V12),
E49: (V9, V14), E50: (V9, V18), E51: (V10, V12), E52: (V10, V15), E53: (V10, V19),
E54: (V11, V12), E55: (V11, V16), E56: (V11, V20)}[/color]

The first 13 reported edges are not valid edges in the refined mesh. They are simply the 13 edges of the original mesh carried over into the refined mesh. We can verify this by checking the edges associated with vertex V0. Note that the edges property of a vertex includes opposite edges in addition to the edges incident on the vertex.

v0 = mesh[NodeId(VERTEX, 0)] v0.edges
[color=green](E13, E14, E15, E46, E47)[/color]
This is the correct collection of edges associated with vertex V0. Note that it does not contain E0 and E1 as reported by mesh.edges.

Looking at the Python bindings, the topology is updated after the mesh is refined, but the code to perform the update is complicated. I’m attaching a notebook that reproduces this issue.

Thanks!

Best,
Dow

Attachment: Edges_after_Refine.ipynb

Since the topology is being updated correctly for vertices, we can work around the issue like this:

true_edges = sorted(list(set(e for v in mesh.vertices for e in mesh[v].edges)), key=lambda e: e.nr) print(len(true_edges)) print(true_edges)
[color=green]44
[E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25, E26, E27, E28, E29, E30, E31, E32, E33, E34, E35, E36, E37, E38, E39, E40, E41, E42, E43, E44, E45, E46, E47, E48, E49, E50, E51, E52, E53, E54, E55, E56][/color]

noted… thank you

The coarse edges are kept on purpose, they are used in H(curl) multigrid.

To figure out the active edges, you can define an H(curl, order=0) - space, and ask for the FreeDofs - Array.

Since these inactive edges (and faces) have let to confusion before, we are thinking of making them optional.

Joachim

Thanks, Joachim!

Your solution is more efficient.

Z = HCurl(mesh, order=0) fd = Z.FreeDofs() true_edges = [e for i, e in enumerate(mesh.edges) if fd[i]]

For a mesh with 743K vertices, this took 3.6 seconds vs. 11.0 seconds for the solution I posted earlier.

Best,
Dow