Source code for tud_lbm.io.plotting.scalar_history_plot

"""Scalar-history analysis plots: a single value vs. timestep."""

from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
from tud_lbm.io.plotting._analysis_common import _BaseAnalysisPlot
from tud_lbm.io.plotting._analysis_common import _extract_rho_2d
from tud_lbm.io.plotting._analysis_common import _extract_u_mag_2d
from tud_lbm.io.plotting._analysis_common import _load_timesteps
from tud_lbm.io.plotting.figure_config import DEFAULT_STYLE
from tud_lbm.registry import comparison_operator

if TYPE_CHECKING:
    from pathlib import Path


@comparison_operator(name="max_velocity")
[docs] class MaxVelocityPlot(_BaseAnalysisPlot): """Plot maximum velocity magnitude over time."""
[docs] name = "max_velocity"
[docs] title = "Maximum velocity vs timestep"
[docs] ylabel = "max(|u|)"
[docs] color = DEFAULT_STYLE.colors["max_velocity"]
[docs] required_keys = ("u",)
[docs] def compute(self, files: list[Path]) -> dict[str, np.ndarray]: """Compute maximum velocity values for each timestep file.""" iters, snapshots = _load_timesteps(files, ("u",)) vals = np.asarray([float(np.max(_extract_u_mag_2d(snap["u"]))) for snap in snapshots], dtype=float) return {"iters": iters, "values": vals}
@comparison_operator(name="density_ratio")
[docs] class DensityRatioPlot(_BaseAnalysisPlot): """Plot max/min density ratio over time."""
[docs] name = "density_ratio"
[docs] title = "Density ratio vs timestep"
[docs] ylabel = "max(rho) / min(rho)"
[docs] color = DEFAULT_STYLE.colors["density_ratio"]
[docs] ylog = True
[docs] required_keys = ("rho",)
[docs] def compute(self, files: list[Path]) -> dict[str, np.ndarray]: """Compute density ratio values for each timestep file.""" iters, snapshots = _load_timesteps(files, ("rho",)) vals = [] for snap in snapshots: rho = _extract_rho_2d(snap["rho"]) min_rho = float(np.min(rho)) safe_min = min_rho if min_rho > 0 else max(min_rho, 1e-30) vals.append(float(np.max(rho)) / safe_min if safe_min != 0 else np.inf) return {"iters": iters, "values": np.asarray(vals, dtype=float)}
@comparison_operator(name="avg_density")
[docs] class AvgDensityPlot(_BaseAnalysisPlot): """Plot average density over time."""
[docs] name = "avg_density"
[docs] title = "Average density vs timestep"
[docs] ylabel = "mean(rho)"
[docs] color = DEFAULT_STYLE.colors["avg_density"]
[docs] required_keys = ("rho",)
[docs] def compute(self, files: list[Path]) -> dict[str, np.ndarray]: """Compute average density values for each timestep file.""" iters, snapshots = _load_timesteps(files, ("rho",)) vals = np.asarray([float(np.mean(_extract_rho_2d(snap["rho"]))) for snap in snapshots], dtype=float) return {"iters": iters, "values": vals}
@comparison_operator(name="total_mass")
[docs] class TotalMassPlot(_BaseAnalysisPlot): """Plot total domain mass (sum of rho) over time."""
[docs] name = "total_mass"
[docs] title = "Total mass vs timestep"
[docs] ylabel = "sum(rho)"
[docs] color = DEFAULT_STYLE.colors["total_mass"]
[docs] required_keys = ("rho",)
[docs] def compute(self, files: list[Path]) -> dict[str, np.ndarray]: """Compute total mass values for each timestep file.""" iters, snapshots = _load_timesteps(files, ("rho",)) vals = np.asarray([float(np.sum(_extract_rho_2d(snap["rho"]))) for snap in snapshots], dtype=float) return {"iters": iters, "values": vals}