dragonfly_sim.utils.gradient_condensation

Newton problems whose residual reads a gradient field that is eliminated from the unknowns.

At p = 0 the RANS model reconstructs a DG0 gradient G of the state by Green-Gauss (core/reconstruction.py),

M_G G = b(U), b(U; tau) = sum over facets of int u_f (x) n : tau ds,

with M_G the diagonal (cell-volume) DG0 mass matrix. G is linear in the facet states, so it is eliminated exactly instead of being carried as an unknown:

R(U) = R_U(U, G(U)), dR/dU = A_UU + A_UG M_G^-1 B_GU,

with A_UU = dR_U/dU at fixed G, A_UG = dR_U/dG and B_GU = db/dU. The product widens the Jacobian’s stencil to the neighbours’ neighbours, which is the stencil of the reconstructed scheme. Everything downstream (SNES, the positivity limiter, the time integrator) still sees a single-field problem in U.

jacobian_mode selects what Newton’s linear solve uses (configure_snes wires it into an existing SNES):

exact operator = preconditioning matrix = A_UU + A_UG M^-1 B_GU compact_pc operator exact, preconditioning matrix A_UU: the compact,

nearest-neighbour part (gradients frozen), as finite-volume codes precondition with their first-order Jacobian. The default: on the coarse SA NACA0012 C-grid it takes the same PTC path as MUMPS, 5x faster, and scales to the 181k-cell STW wing where every exact factorization runs out of memory.

compact operator = preconditioning matrix = A_UU: approximate Newton

(defect correction); converges linearly

Classes

CondensedGradientProblem

NonlinearProblem_mod for R_U(U, G(U)).

CondensedJacobian

A = A_UU + A_UG M^-1 B_GU for a residual form F(U, G), with b_G the UFL

TransposedCondensedOperator

Python-Mat context of the transposed condensed Jacobian without forming it:

Module Contents

class dragonfly_sim.utils.gradient_condensation.CondensedGradientProblem(F, J, u, G, b_G, update_G, inv_mass, jit_options={})

Bases: dragonfly_sim.utils.Nonlinear_utils.NonlinearProblem_mod

NonlinearProblem_mod for R_U(U, G(U)).

G is the gradient Function the residual reads, b_G the UFL form of the Green-Gauss right-hand side, update_G() recomputes G from the current u in place and inv_mass is M_G^-1 as a Vec in G’s layout.

F(x, b)

Assemble the residual F into the vector b.

Args:

x: The vector containing the latest solution b: Vector to assemble the residual into

J(x, A)

Assemble the Jacobian matrix.

Args:

x: The vector containing the latest solution A: The matrix that will hold the Jacobian matrix

configure_snes(snes, mode)

Re-wire snes’s Jacobian for jacobian_mode mode (see the module docstring). Call after the solver is built.

G
MODES = ('exact', 'compact_pc', 'compact')
_A
_A_UU
_condensed
jacobian_mode = 'exact'
update_G
class dragonfly_sim.utils.gradient_condensation.CondensedJacobian(F, u, G, b_G, inv_mass, jit_options={}, A_UU=None, a_UU=None)

A = A_UU + A_UG M^-1 B_GU for a residual form F(U, G), with b_G the UFL Green-Gauss right-hand side (test function on G’s space) and inv_mass M_G^-1 as a Vec in G’s layout. The matrices are plain aij: MatMatMult does not take baij here. The product’s sparsity is fixed by the operands’, so one symbolic product sizes A for good.

_assemble_blocks()
assemble()

Assemble A_UU, A_UG, M^-1 B_GU and A at the current state; G must be up to date.

A
A_UG
A_UU
B_GU
_C
_a
_a_GU
_a_UG
_inv_mass
class dragonfly_sim.utils.gradient_condensation.TransposedCondensedOperator(P, A_UG, B, release_B)

Python-Mat context of the transposed condensed Jacobian without forming it:

A^T x = (A_UU + A_UG B)^T x = P x + B^T (A_UG^T x), P = A_UU^T

with B = M_G^-1 dG/dU (any Mat with mult / multTranspose, e.g. the structured GreenGaussStateOperator). Neither A nor the product A_UG B is ever assembled. It owns P (also the preconditioning matrix), A_UG and B (released through release_B, a callable) and frees them in destroy().

create_mat(comm)
destroy(mat=None)
mult(mat, x, y)
_w