Skip to content

Unstructured mesh: negatively oriented tets are accepted silently and give negative volume-normalised flux #126

Description

@shimwell

Raising this on my fork first for discussion before deciding whether it belongs upstream.

Summary

An unstructured tet mesh whose tetrahedra are negatively oriented (inward winding) is loaded by the MOAB backend without any warning. The raw track-length tally is unaffected, but MOAB reports signed element volumes, so anything that normalises by mesh.volumes silently produces negative flux densities and a badly wrong total. UnstructuredMesh.write_data_to_vtk(volume_normalization=True) is the default, and normalising a track-length tally by element volume is the standard route to a flux density, so this is on a well-travelled path.

Reproduction and measurement

Cube of side 10 meshed to 3874 tets, 14.06 MeV point source, He4, 10 x 20000 particles, openmc 0.15.3 with DAGMC/MOAB enabled. The three meshes are the same tet set, identical count and identical sorted-connectivity fingerprint; only the per-tet vertex ordering differs. Zero degenerate tets in all three. Same seed and source throughout, so the particle histories are identical.

correctly oriented mixed (44.5% negative) all inverted
MOAB / OpenMC load accepted accepted, no warning accepted, no warning
total track-length flux 6.25559042 +/- 4.65e-3 6.25559042 6.25559042
z vs oriented - 0.000 0.000
bins with abs(z) > 3 - 0 0
MOAB total volume (analytic 1000) +1000.0000 +251.2618 -1000.0000
MOAB negative element volumes 0 1724 / 3874 3874 / 3874
MOAB sum of abs(volumes) 1000.0 1000.0 1000.0
volume-normalised flux density, total +14.4495 +4.0606 -14.4495
elements with negative flux density 0 1724 3874

So:

  • Point location and track-length scoring are orientation-insensitive. All three agree to 1e-13 relative (float summation-order noise) and all three match a CSG cell tally over the same cube to z = -0.000. The mesh geometry is being handled correctly.
  • The volumes are not. abs(volumes) is bit-identical across all three, so it is purely the sign. The mixed mesh reports a total volume 74.9 percent low and the inverted one reports exactly minus the right answer.
  • The consequence is silent. No warning is emitted at any stage. The only console output is the unrelated Output for a MOAB mesh (mesh 1) was requested but will not be written.

Why it matters

A negative element volume is never physical, so this is unambiguously bad input, but nothing tells the user. They get a VTK file with negative flux densities in some elements and a total that is wrong by an amount depending on what fraction of their mesh is inverted. If they sum or average across elements, the negatives partially cancel the positives and the result looks plausible.

Meshers do not all guarantee a winding convention, so mixed orientation is a realistic input rather than a contrived one. For context, the same class of defect in our own code (a neutronics element walk that reads outward face normals off a fixed vertex ordering) produced a tally reading 33 percent low, also silently: fusion-neutronics/yamc#316.

Suggested fix

Detect it at load and say so: when an unstructured mesh contains elements of negative volume, warn (or error) naming the count and an example element, rather than proceeding.

I would specifically argue against silently taking abs(volume), even though it would produce the right number here. That repairs a broken mesh behind the user's back and hides the producing mesher's bug, which is the same anti-pattern that let the yamc case run for so long. We recently went the other way there and made bad orientation a hard error with an actionable message, which surfaced the real problem immediately.

Happy to put a PR together if the approach sounds right. The open question is whether warn or error is the correct severity, given that the raw tally is genuinely unaffected and some users may legitimately only ever consume un-normalised totals.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions