Skip to content

Solid surface loads silently vanish on zero-match/zero-area — shell path throws for the identical case #428

Description

@mkofler96

What's wrong

engine/cpp/solve_mfem.cpp has two places where a surface (force/traction/pressure) load on the solid path is silently dropped from the solve instead of erroring:

  • apply_surface_loads, solve_mfem.cpp:563-568 — when a load's face selection matches zero boundary elements (matched == 0), it printfs to stdout and continues, dropping the load entirely.
  • make_surface_load_coefficient, solve_mfem.cpp:480-484 — when a "force" load's matched area is <= 0, it printfs and returns nullptr; the caller (solve_mfem.cpp:582-583) then continues, again dropping the load.

Both cases produce a solve that "succeeds" with the load simply missing — no exception, no message reaching the UI, only a stdout log line nobody sees outside a local build.

Why this is inconsistent, not just theoretically bad

The shell solve path already treats this exact situation as fatal: distributeShellSurfaceLoad in web/src/workers/solver.worker.ts:963-964 does

if (totalArea <= 0)
  throw new Error("shell solve: loaded facets have zero total area");

So the same physical mistake — a load selection that resolves to zero area — is a loud, user-visible error on the shell path and a silent no-op on the solid path. Per CLAUDE.md, a change to the solve payload "almost always has a shell path, a solid path, and a coupled path — cover all three"; here the shell path was hardened but the solid path's equivalent case was not.

It's also the same failure class the project has spent real effort eliminating elsewhere in solve_mfem.cpp — commit 303ba07 (KOF-216) fixed loads silently vanishing via attribute-tag overwrite in this same function, and add_fixed_vertices/apply_point_loads throw kofne::bc::require_valid_vertex/require_min_dofs a few dozen lines away in the same file. The matched == 0 and zero-area cases are the one place in apply_surface_loads that never made the jump from "log it" to "throw it."

(Distinct from #423, which is about a partial face-selection mismatch inside collect_load_elements getting no diagnostic at all — that one's asking for a log to be added; this one is about two cases that already log, but only to stdout, when the shell path throws for the identical situation.)

Suggested fix

Throw (matching the shell path's message and the rest of this file's convention) instead of printf + continue/return nullptr, for both:

  • matched == 0 in apply_surface_loads (solve_mfem.cpp:563-568)
  • area <= 0 for a "force" load in make_surface_load_coefficient (solve_mfem.cpp:480-484)

Location

engine/cpp/solve_mfem.cpp:563-568, :480-484 (solid path) vs. web/src/workers/solver.worker.ts:963-964 (shell path, for comparison)

Found during a scheduled codebase health scan.

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