""" pke_linearize(plant; x_star=nothing, u_star=0.0, Q_star=nothing) Numerical Jacobians via central finite differences. Returns `(A, B, B_w, x_star, u_star, Q_star)` such that for small (dx, du, dw): dx/dt ≈ A dx + B du + B_w dw, where w = Q_sg. Defaults: `x_star` = operating-point steady state, `u_star = 0`, `Q_star = P0`. """ function pke_linearize(plant; x_star=nothing, u_star=0.0, Q_star=nothing) x_star === nothing && (x_star = pke_initial_conditions(plant)) Q_star === nothing && (Q_star = plant.P0) n = length(x_star) eps_rel = 1e-6 eps_abs = 1e-8 f = (x, u, w) -> pke_th_rhs(x, 0.0, plant, t -> w, u) A = zeros(n, n) for k in 1:n h = max(eps_rel * abs(x_star[k]), eps_abs) xp = copy(x_star); xp[k] += h xm = copy(x_star); xm[k] -= h A[:, k] = (f(xp, u_star, Q_star) - f(xm, u_star, Q_star)) ./ (2h) end h = max(eps_rel * abs(u_star), eps_abs) B = (f(x_star, u_star + h, Q_star) - f(x_star, u_star - h, Q_star)) ./ (2h) h = max(eps_rel * abs(Q_star), 1.0) B_w = (f(x_star, u_star, Q_star + h) - f(x_star, u_star, Q_star - h)) ./ (2h) return A, B, B_w, x_star, u_star, Q_star end