Monitoring runs¶
During a simulation x3d2 writes global scalar quantities to a monitoring.csv file at every output step (controlled by n_output in the input file). This file is useful for tracking the evolution of the flow and for comparison with reference data.
Output format¶
The file is a comma-separated CSV with a header line:
# time, enstrophy, div_u_max, div_u_mean
Each subsequent row contains one record per output step.
Quantities¶
Column | Description | Formula |
|---|---|---|
| Simulation time | \(t\) |
| Spatially-averaged enstrophy | \(\mathcal{E} = \frac{1}{2N} \sum |\nabla \times \mathbf{u}|^2\) |
| Maximum of \(|\nabla \cdot \mathbf{u}|\) | Divergence-free check |
| Mean of \(|\nabla \cdot \mathbf{u}|\) | Divergence-free check |
Note
The divergence columns (div_u_max and div_u_mean) measure how well the incompressibility constraint \(\nabla \cdot \mathbf{u} = 0\) is satisfied. Since x3d2 enforces the incompressibility constraint via a pressure projection, these values should remain close to machine precision (typically \(\sim 10^{-14}\) in double precision). A growing divergence indicates a problem with the pressure solver or time-stepping stability.
Example: plotting with Python¶
import pandas as pd
import matplotlib.pyplot as plt
columns = ["time", "enstrophy", "div_u_max", "div_u_mean"]
df = pd.read_csv("monitoring.csv", comment="#", names=columns)
fig, axes = plt.subplots(3, 1, figsize=(8, 8), sharex=True)
axes[0].plot(df["time"], df["enstrophy"])
axes[0].set_ylabel("Enstrophy")
axes[1].plot(df["time"], df["div_u_max"])
axes[1].set_ylabel("div(u) max")
axes[2].plot(df["time"], df["div_u_mean"])
axes[2].set_ylabel("div(u) mean")
axes[-1].set_xlabel("Time")
plt.tight_layout()
plt.savefig("monitoring.png")