
logo produced via intsharplogo_1_rev.yaml — output folder: logo, YAML, and GIF
Basic Usage
python run.py path/to/config.yaml
When you run a simulation:
- A timestamped folder is created in the same directory as the YAML file
- The YAML config is copied into this run folder (original remains for easy re-running)
- All outputs (GIFs, images, data) are saved to the run folder
- Initial conditions (step 0) are always output along with subsequent steps
Example folder structure after a run:
unit_tests/
└── my_config_YYYY-MM-DD_HH:MM:SS/
├── my_config.yaml # copied config
└── <monitor outputs> # GIFs, images, etc.
YAML Configuration Reference
Physics Mode
intsharp supports two physics modes:
- advection_only (default): Scalar advection with optional interface sharpening
- euler: Compressible Euler equations (1D single-phase/two-phase, plus 2D two-phase RTI in FV)
For Euler mode, use physics.mode: euler and configure material(s) and initial conditions. Single-phase example:
physics:
mode: euler
material:
gamma: 1.4 # Ideal gas
p_infinity: 0.0
euler_initial_conditions:
type: riemann
x_discontinuity: 0.5
left: {rho: 1.0, u: 0.0, p: 1.0}
right: {rho: 0.125, u: 0.0, p: 0.1}
euler_bc: transmissive
use_muscl: false # or true for MUSCL + Barth-Jespersen
Two-phase (water-air) uses phase1/phase2 and two_phase_model: 5eq. 2D RTI uses directional BCs (euler_bc_x, euler_bc_y) and optional gravity (physics.gravity). See rayleigh_taylor_2d for the approved 2D example run.
physics:
mode: euler
phase1: {gamma: 1.4, p_infinity: 0.0, rho_ref: 2.0}
phase2: {gamma: 1.4, p_infinity: 0.0, rho_ref: 1.0}
two_phase_model: 5eq
euler_spatial_discretization: fv
euler_bc_x: periodic
euler_bc_y: reflective
gravity: {enabled: true, gx: 0.0, gy: -9.81}
euler_initial_conditions:
type: rti
interface_y0: 0.5
alpha1_top: 1.0
alpha1_bottom: 0.0
perturbation_amplitude: 0.01
perturbation_mode_x: 1
Domain (1D)
1D domains are cell-centered: dx = L/n_points, with grid points at cell centers. This allows CFL = 1 to give exact return after one revolution (no phase drift).
domain:
x_min: -0.5 # Left boundary
x_max: 0.5 # Right boundary
n_points: 100 # Number of grid points (dx = L/n = 0.01)
Domain (2D)
2D domains are cell-centered: dx = Lx/n_points_x, dy = Ly/n_points_y, with grid points at cell centers. This allows CFL = 1 in each direction to give exact return (no phase drift).
domain:
x_min: -0.5 # Left boundary
x_max: 0.5 # Right boundary
n_points_x: 100 # Grid points in x (dx = Lx/n_points_x)
y_min: -0.5 # Bottom boundary
y_max: 0.5 # Top boundary
n_points_y: 100 # Grid points in y (dy = Ly/n_points_y)
Time
time:
dt: 0.01 # Time step size
n_steps: 200 # Number of steps
Velocity
velocity: [0.5] # 1D: advection velocity (list with 1 element)
velocity: [0.5, 0.0] # 2D: (u, v) advection velocity
Fields
fields:
- name: alpha
initial_condition: "0.5 * (tanh((0.1 + x) / 0.02) + tanh((0.1 - x) / 0.02))"
boundary:
type: periodic # or neumann, dirichlet
sharpening: true # optional per-field override
sharpening_method: pm # optional per-field method override
Per-field sharpening: Each field can override the global sharpening on/off via sharpening: true/false, and optionally select a different sharpening method via sharpening_method. This allows comparing multiple sharpening algorithms in the same simulation.
Expression-based Initial Conditions
Initial conditions can be Python expressions evaluated with:
- 1D:
x(grid coordinates) - 2D:
x,y(meshgrid),r = sqrt(x² + y²)(radial distance) - Math functions:
sin,cos,tanh,exp,sqrt,pi,np(numpy)
Image-based Initial Conditions
Instead of an expression, you can specify an image file:
fields:
- name: alpha
initial_condition_image: "shapes/circle.png"
boundary:
type: periodic
The image is processed as follows:
- Converted to grayscale
- Resized to match the domain grid using nearest-neighbor interpolation
- Thresholded: dark pixels (< 0.5) become α = 1, light pixels become α = 0
- A tanh-smoothed interface is applied with ε = 3·dx
Image paths are resolved relative to the YAML config file location.
Boundary Condition Types
| Type | Parameters |
|---|---|
periodic |
(none) |
neumann |
gradient_left, gradient_right |
dirichlet |
value_left, value_right |
Solver
solver:
type: upwind # First-order upwind advection
For compressible runs, use:
physics:
mode: euler
euler_spatial_discretization: fv # fv or dg
flux_calculator: ausm_plus_up # ausm_plus_up or hllc (fv)
dg_order: 1 # if dg: 1, 2, or 3
solver:
type: upwind # ignored in euler mode (kept for backward compatibility)
Timestepper
timestepper:
type: euler # or rk4
For Euler mode with euler_spatial_discretization: fv, this controls time integration directly.
For Euler mode with euler_spatial_discretization: dg, the current solver uses an internal SSP-RK3 update in intsharp/solvers/euler_dg_1d.py (the YAML timestepper is not used for DG at present).
Sharpening (Optional)
sharpening:
enabled: true
method: cl # cl, pm, olsson_kreiss, acls, cls_2010,
# lcls_2012, lcls_2014, cls_2015, cls_2017, scls
eps_target: 0.01 # Target interface thickness
strength: 1.0 # Sharpening strength (Gamma)
method_params: # Optional method-specific parameters
mapping_alpha: 2 # for cls_2010
mapping_gamma: 2 # for cls_2015
scls_alpha: 0.001 # for scls
scls_beta: 1000 # for scls
Per-field method override: Each field can specify its own sharpening method via sharpening_method. This enables comparing multiple methods in a single simulation:
fields:
- name: alpha_cl
sharpening: true
sharpening_method: cl
- name: alpha_pm
sharpening: true
sharpening_method: pm
Output Monitors
When you use run.py, output is written to the timestamped run folder (the output.directory in the YAML is overridden). You can omit output.directory from your YAML.
output:
monitors:
- type: console # Progress bar (no file output)
- type: gif
every_n_steps: 20
field: alpha
- type: gif # Multi-field comparison
every_n_steps: 20
compare_fields:
- field: alpha_no_sharp
color: blue
linestyle: "-"
- field: alpha_pm
color: red
linestyle: "--"
- type: mp4
every_n_steps: 20
field: alpha
- type: png
every_n_steps: 50
field: alpha
- type: svg
every_n_steps: 50
field: alpha
- type: hdf5
every_n_steps: 10
fields: [alpha]
Monitor Types
| Type | Output | Parameters |
|---|---|---|
console |
Progress bar (tqdm) | (none) |
gif |
Animated GIF | field or compare_fields, style, contour_levels |
mp4 |
MP4 video | Same as gif (requires ffmpeg) |
png |
PNG images | field, every_n_steps or at_times |
pdf |
PDF images | field, every_n_steps or at_times |
svg |
SVG images | field, every_n_steps or at_times |
hdf5 |
HDF5 file | fields (list), every_n_steps or at_times |
txt |
Columnar text | field, every_n_steps or at_times |
curve |
Curve format (x, y) | field, every_n_steps or at_times |
metrics |
metrics/*.tsv per field (step, t, ε_char, ε_char/ε_target, δ*_2, δ*_∞) |
fields, optional interface_radius, metrics_eps_target, advection_velocity, initial_center |
Advection runs with per-field sharpening convergence (convergence_tol set) also write convergence_times.tsv in the run directory: one row per sharpening field with t_f = simulation time when that field first satisfies the stop rule.
For 1D advection runs, the runner also exports interface_profiles/<field>_initial.tsv and interface_profiles/<field>_final.tsv (columns x, alpha) at step 0 and at the end of the run, for plotting initial vs. final interface shapes.
Advection-aware metrics: When the hat profile crosses the periodic boundary during advection, set advection_velocity on the metrics monitor so that the field is np.roll-ed back to center before computing ε_char and shape errors:
- type: metrics
every_n_steps: 100
fields: [alpha_cl]
interface_radius: 0.025
advection_velocity: 1.0 # constant velocity for periodic shift-back
initial_center: 0.0 # optional, default 0.0
See gif for details on single-field vs multi-field modes and 2D visualization options.
Parameter Sweep & Stability Analysis
IntSharp includes tools for systematically evaluating sharpening methods across parameter space.
Running a sweep
# Full sweep (all 11 methods, 25x25 grid, n_substeps=[1,5,10])
make sweep
# Custom sweep
python scripts/sharpening_sweep.py --workers 8 --n-eps 30 --n-str 30 \
--methods pm cl olsson_kreiss --substeps 1 10
Results are saved as CSV files in results/sweep/<method>/sweep_nsub<N>.csv.
Generating plots
make plot
This produces three heatmaps per method per n_substeps value:
- Stability map — green/red binary showing where the method is stable and bounded
- Sharpness map — transition cell count (lower = sharper), masked where unstable
- Conservation map — log10(mass drift), masked where unstable
A summary grid PNG comparing all methods side-by-side is also generated.
Proposing new methods (LLM pipeline)
# Requires OPENAI_API_KEY environment variable
make propose
See sharpening_grammar.md for the allowed building blocks.