zoomy_core.analysis package

Contents

zoomy_core.analysis package#

Generic linear-analysis tools for shallow-water-family PDE systems.

The unified analysis entry point is SystemModel (in zoomy_core.model.models.system_model). Every analysis routine in this package consumes a SystemModel and never inspects model-specific attributes.

Package contents:

  • Linearisation around a base state (linearise()) — operates on a SystemModel, returns a SystemModel of perturbation fields.

  • Plane-wave dispersion analysis (ω(k) solutions).

  • Generalised-eigenvalue (“pencil”) form for systems with constraints.

  • Numerical eigenvalue sampling for hyperbolicity over a parameter cube.

The library knows nothing about VAM, SME, ML-SWE, etc. — every model-specific bit is in tutorials/.

zoomy_core.analysis.linearise(sm, base_state, *, eps=None, simplify=True)#

Insert Q = Q_0 + ε δQ, expand, return O(ε) SystemModel.

Parameters:
  • sm (SystemModel) – Input operator-form system.

  • base_state (dict) – Maps each entry in sm.state to its base value (a scalar or an expression in coordinates).

  • eps (sympy Symbol, optional) – Small parameter; created internally if None.

  • simplify (bool) – Apply sp.expand to each linearised operator entry.

Returns:

New SystemModel whose state is [δq_0, …, δq_{n-1}] and whose operator matrices are linearised around base_state.

Return type:

SystemModel

zoomy_core.analysis.plane_wave_dispersion(linear_sm, *, k=None, omega=None, axis=0, solve_for='omega', simplify=True, factor_in_target=True)#

Full dispersion solve.

Returns a dict with:

matrix       — sp.Matrix M(ω, k)
amplitudes   — list of q̂ symbols
determinant  — det M(ω, k)
solutions    — list of ω(k) (or k(ω)) solutions
phase_velocity_solutions — [ω/k for ω in solutions] (omega-mode only)
Parameters:
  • k (Optional[Symbol]) –

  • omega (Optional[Symbol]) –

  • axis (int) –

  • solve_for (str) –

  • simplify (bool) –

  • factor_in_target (bool) –

zoomy_core.analysis.plane_wave_matrix(linear_sm, *, k=None, omega=None, axis=0)#

Insert δq exp(i(k x_axis ω t)) and reduce to a matrix.

linear_sm must be a SystemModel returned by linearise() (state entries are the perturbation symbols δq).

Returns:

  • M (sp.Matrix) – Coefficient matrix such that M · q̂_vector = 0.

  • amplitudes (list[sp.Symbol]) – Amplitude symbols, in the same order as linear_sm.state.

Parameters:
  • k (Optional[Symbol]) –

  • omega (Optional[Symbol]) –

  • axis (int) –

zoomy_core.analysis.extract_quasilinear_pencil(linear_sm)#

Extract (M_t, [M_xa], M_0) from a linearised SystemModel.

Each entry of the linearised SystemModel’s operator slots is expected to be linear in the perturbation state.

Returns:

  • M_t ((n_eq × n_state) sp.Matrix — coefficient of ∂_t δq_j.)

  • M_xa (list of (n_eq × n_state) sp.Matrix — one per spatial axis.)

  • M_0 ((n_eq × n_state) sp.Matrix — coefficient of δq_j (no derivative).)

Return type:

Tuple[MutableDenseMatrix, List[MutableDenseMatrix], MutableDenseMatrix]

zoomy_core.analysis.generalised_eigenvalues(M_x, M_t, *, lam=None, simplify=True)#

Symbolic generalised eigenvalues of the pencil (M_x, M_t).

Solves det(M_x λ M_t) = 0 for λ. Returns a list of solutions.

Caveat — symbolic charpoly degree blows up fast. For larger systems use sample_generalised_eigenvalues (numerical).

Parameters:
  • M_x (MutableDenseMatrix) –

  • M_t (MutableDenseMatrix) –

  • lam (Optional[Symbol]) –

  • simplify (bool) –

Return type:

List[Expr]

zoomy_core.analysis.sample_generalised_eigenvalues(M_x, M_t, parameter_samples, *, dtype=<class 'complex'>, drop_infinite=False)#

For each sample (a dict of symbolic-value → numeric-value), return the numerical generalised eigenvalues of (M_x, M_t) at that sample.

Uses scipy.linalg.eig(A, B) which solves A v = λ B v even when B is singular (in which case some λ are returned as inf). drop_infinite=True filters those out.

Parameters:
  • M_x (MutableDenseMatrix) –

  • M_t (MutableDenseMatrix) –

  • parameter_samples (List[Dict]) –

  • drop_infinite (bool) –

Return type:

List[ndarray]

zoomy_core.analysis.symbolic_eigenvalues_at(sm, base_state, *, axis=0, simplify=True)#

One-shot helper: linearise sm (a SystemModel) at base_state, extract the principal-symbol pencil (M_x_axis, M_t), and return the symbolic generalised eigenvalues.

Parameters:
  • sm – a SystemModel.

  • base_state (Dict) – dict {state_sym: value} for every state entry.

  • axis (int) – which spatial direction’s pencil to use (default 0).

  • simplify (bool) – apply sp.expand to the characteristic poly.

Returns:

list of symbolic eigenvalues.

Return type:

List[Expr]

zoomy_core.analysis.reduce_singular_pencil(M_x, M_t, fields, M_0=None, *, verbose=False)#

Eliminate algebraic-constraint rows + the corresponding fields.

Three classes of “algebraic” rows are handled:

  1. M_t row = 0 and M_x row != 0 — principal-symbol algebraic constraint at high k. Use the M_x row to solve for one field and substitute into all remaining rows (M_x, M_t and M_0 if provided).

  2. M_t row = 0 and M_x row = 0 and M_0 row != 0 — zeroth-order algebraic constraint (k-independent). Use the M_0 row to solve. REQUIRES M_0 argument.

  3. All three rows zero — redundant; drop the row.

Returns (M_x_reduced, M_t_reduced, fields_reduced) with no all-zero M_t rows. If M_0 was provided it is also reduced; access via the returned tuple’s caller side-effect (the matrix is mutated in place — pass a copy if you need the original).

Parameters:
  • M_x (MutableDenseMatrix) –

  • M_t (MutableDenseMatrix) –

  • fields (List) –

  • M_0 (Optional[MutableDenseMatrix]) –

  • verbose (bool) –

Return type:

Tuple[MutableDenseMatrix, MutableDenseMatrix, List]

zoomy_core.analysis.is_hyperbolic_at(M_x, M_t, sample, *, tol=1e-09, drop_infinite=True)#

Evaluate (M_x, M_t) at sample and check eigenvalues.

Returns (hyperbolic, eigenvalues). hyperbolic is True iff every finite eigenvalue has |imag| < tol.

Parameters:
  • M_x (MutableDenseMatrix) –

  • M_t (MutableDenseMatrix) –

  • sample (Dict) –

  • tol (float) –

  • drop_infinite (bool) –

Return type:

Tuple[bool, ndarray]

zoomy_core.analysis.sample_hyperbolicity(M_x, M_t, parameter_ranges, *, n_samples=1000, rng=None, tol=1e-09, drop_infinite=True, constraint_filter=None, max_attempts=10)#

Random-uniform sample over a hyper-rectangle of parameters.

Parameters:
  • M_x (MutableDenseMatrix) – the pencil matrices (sympy).

  • M_t (MutableDenseMatrix) – the pencil matrices (sympy).

  • parameter_ranges (Dict[Any, Sequence]) – dict {sympy_symbol: (lo, hi)} for the variables you want to sample. Symbols not in this dict must already be substituted-out in the pencil (e.g. fixed at chosen values).

  • n_samples (int) – number of accepted samples to draw.

  • rng (Optional[Generator]) – optional np.random.Generator.

  • tol (float) – imaginary-part threshold for “real”.

  • drop_infinite (bool) – drop infinite generalised eigenvalues (typical for systems with constraints).

  • constraint_filter (Optional[Callable[[Dict], bool]]) – optional callable sample_dict bool. A sample is rejected (and another drawn) if this returns False — useful for excluding e.g. h ≤ 0.

  • max_attempts (int) – per accepted sample, how many draws before giving up.

Return type:

HyperbolicityReport

Returns HyperbolicityReport.

zoomy_core.analysis.plot_dispersion(result, k_range, *, k_var=None, ax=None, n_points=200, mode='phase_velocity', fixed_subs=None, references=None, nondimensionalise_by=None, squared=False, title=None, mode_labels=None, drop_zero_modes=True, **plot_kwargs)#

Plot dispersion curves from a plane_wave_dispersion result.

Parameters:
  • result (Dict) – dict from plane_wave_dispersion().

  • k_range (Tuple[float, float]) – (k_lo, k_hi) numeric range over which to evaluate.

  • k_var (Optional[Symbol]) – wavenumber symbol; auto-detected as Symbol('k') if absent.

  • ax – matplotlib axis to draw on; new figure created if None.

  • n_points (int) – grid resolution along k.

  • mode (str) – 'phase_velocity' (C = ω/k) or 'omega'.

  • fixed_subs (Optional[Dict]) – dict {Symbol: number} for the non-k free symbols.

  • references (Optional[Dict[str, Callable]]) – dict {label: callable(k_arr)} for overlay curves (e.g. {'Airy': lambda k: np.sqrt(np.tanh(k*H)/(k*H))}).

  • nondimensionalise_by (Optional[Tuple[str, Any]]) – tuple (label, expr); if given, the y-axis becomes y / expr and the label includes label (e.g. ('gH', g*H)).

  • squared (bool) – if True, plot y**2 instead of y (for C²/(gH)).

  • title (Optional[str]) – optional plot title.

  • mode_labels (Optional[List[str]]) – if given, list of length len(solutions) for the legend; otherwise mode 0, mode 1, .

  • drop_zero_modes (bool) – if True (default), skip ω-solutions that are identically zero (trivial constraint modes).

Returns:

{'k', 'curves', 'figure', 'axis'}.

zoomy_core.analysis.plot_hyperbolic_region_2d(M_x, M_t, axis_a, axis_b, fixed_subs, *, ax=None, n_a=100, n_b=100, tol=1e-09, drop_infinite=True, show='binary', title=None, cmap=None)#

2D color map of hyperbolicity over a chosen parameter pair.

Each (a_val, b_val) grid point is evaluated by:

  1. Substituting all of fixed_subs plus {axis_a[0]: a_val, axis_b[0]: b_val} into M_x and M_t.

  2. Computing the generalised eigenvalues of the pencil (M_x_num, M_t_num) via scipy.linalg.eig.

  3. Filtering infinite eigenvalues (constraint modes); the state is hyperbolic iff every remaining eigenvalue has |imag| < tol.

Parameters:
  • M_x – pencil matrices (sympy).

  • M_t – pencil matrices (sympy).

  • axis_a (Tuple[Symbol, float, float]) – (symbol_a, lo, hi) for the x-axis parameter.

  • axis_b (Tuple[Symbol, float, float]) – (symbol_b, lo, hi) for the y-axis parameter.

  • fixed_subs (Dict) – dict of values for every other free symbol in M_x and M_t.

  • n_a (int) – grid resolution.

  • n_b (int) – grid resolution.

  • show (str) – 'binary' (default — green=hyperbolic, red=non) or 'imag_max' (color by max |Im λ|).

  • cmap (Optional[str]) – optional matplotlib colormap name.

  • tol (float) –

  • drop_infinite (bool) –

  • title (Optional[str]) –

Returns:

dict with a_grid, b_grid, is_hyperbolic (bool 2D array), imag_max (float 2D array), figure, axis.

Submodules#