Skip to content

Time-dependent Dirichlet BCs are broken in solve(): essential values inserted at PETSC_MIN_REAL, mesh.t kernels see -1.8e308 #410

Description

@lmoresi

Found by the adversarial review of the #407 fix (2026-07-24) — pre-existing, upstream of that change.

A Dirichlet BC that references mesh.t NaNs the solve:

poisson.add_dirichlet_bc(mesh.t, "Bottom")
poisson.solve(time=2.0)   # DIVERGED_FNORM_NAN; wall values -inf

Mechanism (read in PETSc source): the solve-side boundary insertion goes through DMPlexSNESComputeBoundaryFEM, which hard-codes time=PETSC_MIN_REAL into DMPlexInsertBoundaryValues; that value lands as petsc_t (-1.8e308) in the JIT'd essential-BC kernel, so any BC expression containing mesh.t evaluates to garbage. solve()'s docstring claim that 'expressions using mesh.t evaluate at this time' is empirically false for Dirichlet BCs.

Note the working counter-evidence: _assemble_volume_reaction(time=2.0) (post-#407) inserts g(t) correctly via a direct DMPlexInsertBoundaryValues call with the real time — so the kernels and the insertion machinery are fine; only the solve path's hard-coded PETSC_MIN_REAL is the problem. Fix direction: insert essential values explicitly with the solver's non-dimensional time before SNESSolve (or set the DM time in a way the PETSc path picks up — UW_DMSetTime exists but the BoundaryFEM path ignores it).

Related latent detail: boundary_flux() never forwards a solve time to _assemble_volume_reaction, so once this is fixed, CBF on a time-dependent wall would read g(0) — forward the time in the same change.

Underworld development team with AI support from Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions