dragonfly_sim.utils.solver_utils

Attributes

MIN_POSITIVITY_THETA

POSITIVITY_FLOOR

_KSP_NORM_TYPE_NAMES

_KSP_REASON_NAMES

Functions

_enum_name_map(enum_cls)

Reverse map {code: name} for a petsc4py enum-like class.

compute_positivity_preserving_theta(comm, x_arr, dx_arr)

Computes the maximum theta <= initial_theta such that x_new = x_arr - theta * dx_arr

ksp_converged_reason_name(reason)

Human-readable name for a PETSc KSP convergence reason code.

ksp_norm_type_name(norm_type)

Human-readable name for a PETSc KSP norm type.

ksp_pc_side_name(pc_side)

Human-readable name for a PETSc preconditioner side (LEFT/RIGHT/SYMMETRIC).

locate_positivity_limiting_nodes(x_arr, dx_arr, ...[, ...])

Find which local nodes make x_arr - theta_probe*dx_arr unphysical.

Module Contents

dragonfly_sim.utils.solver_utils._enum_name_map(enum_cls)

Reverse map {code: name} for a petsc4py enum-like class.

petsc4py exposes most codes under several aliases – PC.Side has both “L” and “LEFT” for 0, KSP.ConvergedReason both “DIVERGED_PC_FAILED” and “DIVERGED_PCSETUP_FAILED” for -11 – so the map has to choose. Longest name first, ties broken alphabetically: longest picks the descriptive alias over the terse one (which is the whole point of printing a name instead of the integer), and the tie-break makes the result identical on every run rather than dependent on dir() ordering.

dragonfly_sim.utils.solver_utils.compute_positivity_preserving_theta(comm, x_arr, dx_arr, gamma=1.4, initial_theta=1.0, min_theta=None, block_size=4)

Computes the maximum theta <= initial_theta such that x_new = x_arr - theta * dx_arr has positive mass density and positive pressure everywhere.

Returns the step length only. To find out WHICH nodes bounded it – the question a collapsed theta raises – pass twice the returned value to locate_positivity_limiting_nodes.

dragonfly_sim.utils.solver_utils.ksp_converged_reason_name(reason)

Human-readable name for a PETSc KSP convergence reason code.

Worth printing next to the iteration count because the count alone cannot distinguish the two failures that call for opposite responses: DIVERGED_MAX_IT means a hard but well-posed operator that simply exhausted its Krylov budget (tune the solver), while DIVERGED_BREAKDOWN or DIVERGED_PCSETUP_FAILED means the Arnoldi process or the preconditioner itself failed (the operator or the coarse space is broken). Both show up as “ran to max_it” in a log that reports only iterations.

Unknown codes come back as “REASON(<n>)” rather than raising – this is a diagnostic and must never be the thing that breaks a solve.

dragonfly_sim.utils.solver_utils.ksp_norm_type_name(norm_type)

Human-readable name for a PETSc KSP norm type.

This is what says whether a reported residual norm is the true ||b - Ax|| or the preconditioned one, which decides whether a norm LARGER than ||b|| is impossible (UNPRECONDITIONED, as fgmres defaults to) or unremarkable (PRECONDITIONED, as gmres defaults to). Without it the number cannot be read at all.

dragonfly_sim.utils.solver_utils.ksp_pc_side_name(pc_side)

Human-readable name for a PETSc preconditioner side (LEFT/RIGHT/SYMMETRIC).

dragonfly_sim.utils.solver_utils.locate_positivity_limiting_nodes(x_arr, dx_arr, theta_probe, gamma=1.4, block_size=4, floor=POSITIVITY_FLOOR)

Find which local nodes make x_arr - theta_probe*dx_arr unphysical.

Diagnostic companion to compute_positivity_preserving_theta, which returns the surviving step length and says nothing about what bounded it. Pass theta_probe = twice the accepted theta – the smallest step that bisection actually rejected – and the nodes reported here are exactly the ones that forced the final halving.

Rank-local and pure numpy: the caller owns the MPI reduction and the dof-coordinate lookup. block is an index into the BLOCKS of x_arr, which for a blocked function space is also a row index into that space’s local dof coordinates.

Returns a dict:
n_density, n_pressure, n_nonfinite

local counts of nodes violating each way, for the caller to sum across ranks. One violating node out of millions and a whole region going unphysical at once are different problems, and the count is what tells them apart.

block

block index of this rank’s WORST violator, or None if this rank has none – in which case the keys below are absent.

severity

trial value over current value at that node, so that a density and a pressure violation are comparable and one argmin ranks the whole set; more negative is a worse overshoot, -inf for a non-finite trial state.

constraint

“density”, “pressure” or “non-finite”.

rho, p, rho_trial, p_trial, d_rho, d_rhou_norm, d_rhoE

the state, the trial state and the update at that node.

dragonfly_sim.utils.solver_utils.MIN_POSITIVITY_THETA = 1e-06
dragonfly_sim.utils.solver_utils.POSITIVITY_FLOOR = 0.0001
dragonfly_sim.utils.solver_utils._KSP_NORM_TYPE_NAMES = None
dragonfly_sim.utils.solver_utils._KSP_REASON_NAMES = None