Model configuration
VVMex reads runtime settings from one JSON file. Start by copying a runnable
case from rundata/input_configs/default_cases/, then use this page as a
reference while editing it. Writing a complete case from scratch is rarely the
fastest route.
submit.py passes the selected file to VVMex. Direct invocations may instead
provide the JSON path as the first non-option argument.
How to read this page
| Default column | Meaning |
|---|---|
| required | The key must be present. The run stops at startup with Configuration error: Key '<path>' not found. |
| a value | The key is optional and this is what the code uses when it is absent. |
Four things about how the file is parsed are worth knowing before you edit one:
- Keys are looked up by dotted path, not validated as a schema. A key the model does not know is simply never read.
- A misspelled optional key is therefore silent.
"enable_p3"written as"enable_P3"leaves P3 off and prints no warning. When a setting appears to have no effect, check the spelling and nesting against this page first. - The one exception is
output.bp5, which rejects unknown keys and invalid values outright, and cross-checks every resolved setting across all compute ranks before opening the dataset. - Keys starting with
__or_are inline comments for humans and are never read.
Types are int, real (double, or float in a single-precision build), bool, string, list, or object.
Command-line options
| Argument | Meaning |
|---|---|
path/to/config.json |
Optional. If present as the first non-flag argument, selects the configuration file. Flags such as --io-tasks are skipped when resolving this path. |
--io-tasks N |
Reserve N MPI ranks for asynchronous I/O. Only meaningful with output.engine = "SST"; see Output. |
Example:
cd $VVM_ROOT
./submit.py -c /path/to/my_run.json --compute 1 --local
# Advanced direct MPI only
mpirun -np 1 ./build/vvm /path/to/my_run.json
The full submit.py option list is in Job submission.
How to edit a run
Most experiments follow the same editing order:
- Set the grid and time controls (
grid,simulation). - Choose the sounding profile and spatial NetCDF inputs (
initial_conditions,netcdf_reader). - Choose restart behavior, if any (
restart). - Choose output engine, fields, and subdomain (
output). - Enable dynamics forcings and tendency terms (
dynamics). - Enable physics packages and their call frequencies (
physics). - Tune acceleration options (
optimization) only after the run is physically configured.
Keep JSON paths relative to the directory where submit.py starts the model, normally the project root.
Copy-and-edit defaults
Start every new experiment by copying a complete, runnable case. This is the fastest and safest way to obtain all required values and a consistent set of fields:
Then replace the top-level blocks below in my_case.json as needed. Each block
is valid JSON and can be copied directly; it uses documented defaults wherever
a default exists. Required settings have no model default, so the starter values
for those keys are intentionally small and should be changed for the experiment.
The reference tables remain the complete source for every supported key, constraint, and engine-specific behavior.
Default-case inputs
Use the default cases when you want a known sample setup before designing your own experiment:
./submit.py --local --preset <your_preset_name> -c ./rundata/input_configs/default_cases/advection_u.json --compute 1
The three default-case directories are:
| Directory | Purpose |
|---|---|
rundata/input_configs/default_cases/ |
Runnable JSON files such as advection_u.json, 2dbubble.json, rcemip.json, sea_grass_mountain.json, and taiwanvvm_2048.json. |
rundata/initial_conditions/profiles/default_cases/ |
Sounding/profile text files used by those JSON files. |
rundata/initial_conditions/spatial/default_cases/ |
Spatial NetCDF inputs for topography, surface, and land fields. These can be generated with tools/generate_init_nc.py. |
For the complete case list and generation notes, see Default cases.
grid
Global mesh, halo width, horizontal boundary behavior, and vertical coordinate construction.
| Key | Type | Default | Meaning |
|---|---|---|---|
nx, ny, nz |
int | required | Global domain size in x, y, and z. MPI decomposes this domain across compute ranks. |
n_halo_cells |
int | required | Halo width used by stencil operations and MPI halo exchange. 2 suits every scheme except weno5, whose flux stencil reaches three cells past the last interior cell. This is one grid-wide setting, so a single tracer using weno5 forces 3 for the whole run, whatever the other tracers use. A run that gets this wrong stops at startup with Tracer '<name>': weno5 halo width is insufficient; configured 2, required 3. |
dx, dy |
real | required | Horizontal grid spacing in meters. Uniform. |
dz |
real | required | Nominal vertical spacing in meters. |
dz1 |
real | required | Spacing of the stretched lower layers. With dz1 < dz the vertical grid is stretched from dz1 near the surface toward dz aloft; dz1 == dz gives a uniform column. |
boundary_condition.x |
string | "periodic" |
Lateral boundary type in x: periodic or zero_gradient. Anything other than zero_gradient is treated as periodic, so a typo silently gives you a periodic boundary. |
boundary_condition.y |
string | "periodic" |
Same, in y. |
fix_lonlat |
bool | false |
Fixed longitude/latitude handling for Taiwan-oriented real-case inputs. |
vertical_coordinate_type |
string | "default" |
default, taiwanvvm, or rcemip. Selects how z_up/z_mid are built, how the profile is interpolated, and the output coordinate convention. |
rcemip_grid_data_path |
string | ./rundata/initial_conditions/profiles/snd_rcemip_anal300_v3.txt |
Profile the rcemip coordinate is built from. Read only when vertical_coordinate_type is rcemip. |
Use taiwanvvm when you need the TaiwanVVM-style vertical coordinate and output coordinate handling. Use default for ordinary idealized or simple real-case tests unless the case explicitly requires another coordinate.
Copy and edit this starter grid:
{
"grid": {
"nx": 32,
"ny": 32,
"nz": 33,
"n_halo_cells": 2,
"dx": 100.0,
"dy": 100.0,
"dz": 500.0,
"dz1": 100.0,
"boundary_condition": { "x": "periodic", "y": "periodic" },
"fix_lonlat": false,
"vertical_coordinate_type": "default",
"rcemip_grid_data_path": "./rundata/initial_conditions/profiles/snd_rcemip_anal300_v3.txt"
}
}
simulation
| Key | Type | Default | Meaning |
|---|---|---|---|
total_time_s |
real | required | Total simulated time in seconds. |
dt_s |
real | required | Model time step in seconds. Several physics frequencies must be divisible by this value. |
output_interval_s |
real | required | Output cadence in simulated seconds. With dt_s: 1.0 and output_interval_s: 600.0 you get one output every 600 model steps. |
idealized_test |
string | "none" |
Built-in dynamics test: none, advection_u, advection_v, advection_w, stretching, twisting, or 2dbubble. |
Setting idealized_test to anything but none replaces normal initialization with the test's analytic state and disables the spatial NetCDF read. For production-like runs, keep it none.
Copy and edit these small-run values:
{
"simulation": {
"total_time_s": 1500.0,
"dt_s": 1.0,
"output_interval_s": 50.0,
"idealized_test": "none"
}
}
initial_conditions
The one-dimensional sounding/profile and optional initial perturbations.
A run with simulation.idealized_test: "none" — that is, any real case — must supply initial_conditions.format (which must be txt), initial_conditions.source_file, and netcdf_reader.source_file; the run stops at startup otherwise. Built-in idealized tests build their own state and may omit all three.
| Key | Type | Default | Meaning |
|---|---|---|---|
format |
string | required unless idealized | txt or netcdf; any other value is rejected. txt reads a sounding through TxtReader. |
source_file |
string | required unless idealized | Path to the profile used to initialize pressure, thermodynamics, and winds. Required whenever format is txt. |
perturbation |
string | "none" |
Initial perturbation preset: none, 2dbubble, or 3dbubble. Skipped entirely when restart.enable is true. |
constant_upper_wind.enable |
bool | false |
Hold winds above pressure_threshold_Pa constant while reading the text profile. |
constant_upper_wind.pressure_threshold_Pa |
real | 25000.0 |
Pressure threshold for that handling. |
reapply_spatial_initial_conditions |
bool | false |
Re-read netcdf_reader.source_file after the base state is assigned, so spatial fields overwrite anything the profile/topography path derived. Applied before restart loading. |
rcemip_consistent_reference_state |
bool | false |
Correct two reference-state errors on the rcemip vertical coordinate. Ignored on every other coordinate. See below. |
!!! warning "rcemip_consistent_reference_state changes results"
Only meaningful when `grid.vertical_coordinate_type` is `rcemip`. With it
off — the default — the reference state is built the way v1.0.0 built it:
the Exner function uses a hardcoded exponent of `2/7` instead of
`constants.Rd / constants.Cp`, and the density is `p/(Rd*T)` rather than
`p/(Rd*Tv)`. Both are wrong, and the second is the larger error: omitting
the virtual-temperature correction makes the initial density about 0.9 %
too high for a moist RCEMIP sounding.
The default is `false` because `tests/references/rcemip.json` encodes the
v1.0.0 numbers. Turning it on shifts `Tbar` by 0.043 K, `pibar` by 5.9e-5,
`rhobar` and `rhobar_up` by 0.37 % in the mean, and the surface fluxes by
0.9 %, so `Verify_physics_rcemip` fails until the reference is regenerated
with `tests/scripts/check_output.py --update --digest-dtype float32`.
!!! note "pressure_threshold_Pa has two different fallbacks"
The profile reader falls back to `25000.0` Pa, but the area-mean nudging
forcing (`dynamics.forcings.areamn`) falls back to `3000.0` Pa for the same
key. If you enable both `constant_upper_wind` and `areamn`, set the key
explicitly so the two agree.
Default-case profiles live under rundata/initial_conditions/profiles/default_cases/. The profile must be consistent with the vertical coordinate choice and the physics you enable.
For an ordinary, non-idealized run, copy this input block and replace the profile path:
{
"initial_conditions": {
"format": "txt",
"source_file": "./rundata/initial_conditions/profiles/default_cases/profile_dry.txt",
"perturbation": "none",
"constant_upper_wind": {
"enable": false,
"pressure_threshold_Pa": 25000.0
},
"reapply_spatial_initial_conditions": false,
"rcemip_consistent_reference_state": false
}
}
netcdf_reader
Spatial two-dimensional fields such as longitude, latitude, topography, land mask, vegetation, soil, and surface parameters.
| Key | Type | Default | Meaning |
|---|---|---|---|
source_file |
string | required unless idealized | Spatial NetCDF file, usually under rundata/initial_conditions/spatial/. When absent, no spatial read happens at all. |
Tg_source |
string | "atmosphere" |
atmosphere derives ground temperature from the atmospheric state at the topography level; netcdf keeps the Tg field read from the file. Any other value keeps existing values and warns. |
variables_to_read.1d |
list | (empty) | 1-D variables to read from the file. |
variables_to_read.2d |
list | (empty) | 2-D variables to read. Typically lon, lat, topo, sea_land_ice_mask, vegtype, soiltype, slopetype, Tg, albedo, gvf, lai, shdmax, shdmin. |
variables_to_read.3d |
list | (empty) | 3-D variables to read. Enabled tracers and their _source fields are always appended to this list, whether or not it is given. |
Every listed variable must exist in the file — a missing one is an error, not a warning. The default spatial NetCDF files can be generated with tools/generate_init_nc.py. For Taiwan-style cases, generate or prepare the file before submission; see TaiwanVVM example.
For the small default cases, this is the matching spatial-input block. Remove fields from the list when the file does not contain them:
{
"netcdf_reader": {
"source_file": "./rundata/initial_conditions/spatial/default_cases/init_regression_test.nc",
"Tg_source": "atmosphere",
"variables_to_read": {
"1d": [],
"2d": ["lon", "lat", "topo", "sea_land_ice_mask"],
"3d": []
}
}
}
restart
Whether the model initializes prognostic fields from an existing output file.
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | false |
Enables restart loading. |
source_file |
string | required when enabled | Restart source. .h5 goes through the HDF5 restart reader, .bp through the BP5 restart reader, .nc through the PnetCDF reader; any other extension is an error. |
legacy_time_s |
real | (none) | Elapsed simulation seconds to resume from, for a file that stores no clock of its own. Explicit opt-in; warns when used. |
allow_filename_time_fallback |
bool | false |
Restores the old behaviour of deriving the restart time from the digits in the file name (index * file_interval_s). Warns loudly when enabled. |
file_interval_s |
real | 3600.0 |
Seconds represented by one numbered output index. Consulted only when allow_filename_time_fallback is true. |
ignore_stored_step |
bool | false |
Discard the model_step stored in the file and re-derive the step from simulation.dt_s. Use when dt was deliberately changed on restart. |
step_index |
int | -1 |
BP5 only. Which ADIOS2 step of the .bp dataset to resume from; -1 is the last one written. An .h5 file holds a single time, so this key has no meaning there. |
variables_to_read.1d |
list | (none) | Explicit 1-D restart variable list. |
variables_to_read.2d |
list | (none) | Explicit 2-D restart variable list. |
variables_to_read.3d |
list | inferred | Explicit 3-D restart variable list. See below for how it is inferred. |
If no explicit restart.variables_to_read.3d is supplied, the reader (HDF5 or BP5 — they share this selection) selects prognostic variables from dynamics.prognostic_variables and filters them through output.fields_to_output. That means fields needed after restart should either be listed explicitly under restart.variables_to_read or be included in output.fields_to_output.
When restart is enabled, the restart state replaces the normal perturbation initialization.
How the restart time and step are recovered
The simulation clock comes from metadata stored inside the restart file, never from its name. Renaming a restart file does not change the time it resumes from. Output files carry two scalars for this:
| Variable | Meaning |
|---|---|
model_time_s |
Elapsed simulation time in seconds (double). |
model_step |
Exact integration-step count (64-bit integer). |
The model tries, in order:
- Stored time and stored step. They are cross-checked against
simulation.dt_s; iftimeandstep * dtdisagree by more than a serialization tolerance the run stops and prints both values, the configureddt, the expected time and the source file. Neither value is silently preferred. - Stored time alone, with
step = round(time / dt). restart.legacy_time_s, for files predating the metadata. Prints a rank-0 warning.- The digits in the file name, only when
restart.allow_filename_time_fallbackis true. Prints a prominent rank-0 warning, because the file name then is the clock.
Without one of these the run stops rather than guessing. The recovered values are broadcast from rank 0, so every rank resumes from an identical time and step, and rank 0 reports them:
NetCDF restart sources are written outside this model, so only unambiguous metadata is accepted: model_time_s / model_step as scalar variables or as global attributes, or a time variable whose units attribute says plain seconds. A calendar time ("hours since ...") is deliberately not read as an elapsed time — such a file needs restart.legacy_time_s.
Restart files are ordinary output files; there is no separate restart output path. What each engine leaves behind to restart from:
output.engine |
Restart source it produces | Read by |
|---|---|---|
HDF5 |
<prefix>_NNNNNN.h5, one per output time |
Hdf5RestartReader |
SST |
the same .h5 files, written by the I/O server rather than the compute ranks |
Hdf5RestartReader — SST is a transport, not a restart format |
BP5 |
<prefix>.bp, one dataset holding every output time |
Bp5RestartReader, which also needs step_index |
The keys above are the same for all three; only step_index is engine-specific, because only BP5 stores more than one time per source. Field selection and clock recovery are shared code, so the same run resumes identically whichever of the three wrote its source.
Copy-ready restart configurations
Copy the example matching the desired output behavior and merge its top-level blocks into the case file. These examples resume at t = 3600 s and run until t = 7200 s.
HDF5 restart into a new output directory
This also applies to an .h5 restart file produced by SST.
{
"simulation": {
"total_time_s": 7200.0,
"dt_s": 1.0,
"output_interval_s": 600.0
},
"restart": {
"enable": true,
"source_file": "./output/my_case/vvm_output_000006.h5"
},
"output": {
"engine": "HDF5",
"output_dir": "./output/my_case_resumed",
"output_filename_prefix": "vvm_output",
"output_initial_step": true,
"precision": "native",
"fields_to_output": [
"thbar", "rhobar", "topo", "u", "v", "w",
"th", "qv", "xi", "eta", "zeta"
]
}
}
BP5 restart into a new dataset
Use this when the original history should remain unchanged and the resumed run
should create ./output/my_case_resumed/vvm_output.bp.
{
"simulation": {
"total_time_s": 7200.0,
"dt_s": 1.0,
"output_interval_s": 600.0
},
"restart": {
"enable": true,
"source_file": "./output/my_case/vvm_output.bp",
"step_index": -1
},
"output": {
"engine": "BP5",
"output_dir": "./output/my_case_resumed",
"output_filename_prefix": "vvm_output",
"output_initial_step": true,
"precision": "native",
"fields_to_output": [
"thbar", "rhobar", "topo", "u", "v", "w",
"th", "qv", "xi", "eta", "zeta"
],
"bp5": {
"num_subfiles": 2,
"existing_dataset": "error"
}
}
}
BP5 restart and append to the same dataset
Use this to preserve the old steps and add new steps to
./output/my_case/vvm_output.bp.
{
"simulation": {
"total_time_s": 7200.0,
"dt_s": 1.0,
"output_interval_s": 600.0
},
"restart": {
"enable": true,
"source_file": "./output/my_case/vvm_output.bp",
"step_index": -1
},
"output": {
"engine": "BP5",
"output_dir": "./output/my_case",
"output_filename_prefix": "vvm_output",
"output_initial_step": false,
"precision": "native",
"fields_to_output": [
"thbar", "rhobar", "topo", "u", "v", "w",
"th", "qv", "xi", "eta", "zeta"
],
"bp5": {
"num_subfiles": 2,
"existing_dataset": "append"
}
}
}
The append safeguards are intentional: the source and destination must resolve
to the same .bp dataset, step_index must be -1, and
output_initial_step must be false. This prevents truncating later history or
writing the restart step twice.
For every restart:
total_time_sis the absolute end time, not time to add after restarting.- Required restart fields must exist in the source. Keep them in
output.fields_to_output, or setrestart.variables_to_readexplicitly. - The first step uses first-order history initialization because AB2 tendency history is not stored, so a restart is not bit-for-bit identical to an uninterrupted run.
output
ADIOS2 output, field selection, and optional subsetting. Engine trade-offs and sizing guidance are in Output.
| Key | Type | Default | Meaning |
|---|---|---|---|
output_dir |
string | required | Destination directory. submit.py creates it before launching. |
output_filename_prefix |
string | required | Base name for the files, the .bp dataset, or the SST stream. |
engine |
string | "HDF5" |
HDF5 (one file per output time), SST (streams to dedicated I/O ranks), or BP5 (one multi-step .bp dataset written directly by compute ranks). |
fields_to_output |
list | required | Ordered list of state fields to write. A name the run never registered is skipped with a message; on HDF5 and SST a name that is not a known optional field either is an error, so typos are still caught. Must be non-empty and duplicate-free for BP5. |
precision |
string | "native" |
On-disk float type for field data only, on every engine: native (follows VVM::Real), float32/float/single, or float64/double. Case-insensitive. Clocks and coordinates always stay VVM::Real. Narrowing output narrows what a later restart recovers, on whichever engine produced the restart source. |
output_initial_step |
bool | true |
Write step 0 before the first model step. |
output_grid.x_start, .y_start, .z_start |
int | 0 |
Inclusive lower index bound per direction. |
output_grid.x_end, .y_end, .z_end |
int | -1 |
Inclusive upper index bound; -1 means "to the end". Halo cells are never written. |
For normal HDF5 history, copy this block and set the output directory and field
list. hdf5_collective_mpio is included at its default so it is easy to change
when a parallel filesystem benefits from collective I/O.
{
"output": {
"output_dir": "./output/my_run",
"output_filename_prefix": "vvm_output",
"engine": "HDF5",
"fields_to_output": ["u", "v", "w", "th", "qv"],
"precision": "native",
"output_initial_step": true,
"output_grid": {
"x_start": 0, "x_end": -1,
"y_start": 0, "y_end": -1,
"z_start": 0, "z_end": -1
},
"hdf5_collective_mpio": false
}
}
output — HDF5 only
| Key | Type | Default | Meaning |
|---|---|---|---|
hdf5_collective_mpio |
bool | false |
Use collective MPI-IO in the HDF5 engine instead of independent writes. |
output — SST only
| Key | Type | Default | Meaning |
|---|---|---|---|
queue_limit |
int | 1 |
ADIOS2 SST queue depth. The queue-full policy is Block, so a small value keeps the writers close to the readers. |
data_transport |
string | "WAN" |
SST data plane: WAN (sockets), RDMA, or empty/AUTO to let ADIOS2 choose. Case-insensitive. |
control_transport |
string | "sockets" |
SST control plane. |
For SST, replace the HDF5 output block with this one and launch with
submit.py --io <number-of-io-ranks>:
{
"output": {
"output_dir": "./output/my_run",
"output_filename_prefix": "vvm_output",
"engine": "SST",
"fields_to_output": ["u", "v", "w", "th", "qv"],
"precision": "native",
"output_initial_step": true,
"output_grid": {
"x_start": 0, "x_end": -1,
"y_start": 0, "y_end": -1,
"z_start": 0, "z_end": -1
},
"queue_limit": 1,
"data_transport": "WAN",
"control_transport": "sockets"
}
}
output.bp5
Read only when engine is BP5. Unknown keys and invalid values are errors,
and every resolved setting is compared across compute ranks before opening the
dataset.
For a normal run, copy this block and change the directory, prefix, fields, and subfile count:
{
"output": {
"engine": "BP5",
"output_dir": "./output/my_run",
"output_filename_prefix": "vvm_output",
"output_initial_step": true,
"precision": "native",
"fields_to_output": ["u", "v", "w", "th", "qv"],
"bp5": {
"aggregation_type": "TwoLevelShm",
"num_subfiles": 10,
"stats_level": 0,
"async_write": false,
"buffer_mode": "direct",
"existing_dataset": "error"
}
}
}
Choose how an existing target is handled:
existing_dataset |
Behavior |
|---|---|
"error" |
Safe default. Stop if <output_dir>/<prefix>.bp already exists. |
"replace" |
Delete and recreate an existing dataset. Use only when its history is disposable; it cannot replace the active restart source. |
"append" |
Continue the same BP5 restart dataset. Use the complete in-place append example. |
Most runs only need num_subfiles and existing_dataset. The remaining keys
are optional performance controls:
| Key | Default | Meaning |
|---|---|---|
aggregation_type |
"TwoLevelShm" |
Currently the only accepted value. |
num_subfiles |
10 |
Positive requested data subfile count. ADIOS2 caps it at the compute-rank count. |
stats_level |
0 |
0 minimises statistics work; 1 enables BP5 statistics. Other values are rejected. |
async_write |
false |
Enables ADIOS2 background writing. |
buffer_mode |
"direct" |
direct uses CPU memory selection when compatible; pack uses staging buffers. CUDA and precision conversion automatically resolve to packed staging. |
Do not use output.bp5.overwrite or output.bp5.precision in new cases. They
remain accepted only for compatibility: overwrite: false/true maps to
existing_dataset: "error"/"replace", while BP5-scoped precision overrides
the engine-neutral output.precision. A configuration cannot contain both
overwrite and existing_dataset.
!!! note "num_subfiles can only ever reduce the file count"
ADIOS2 writes one subfile per aggregator and cannot have more aggregators
than ranks, so the value is clamped. Measured on a 2-step case:
| ranks \ requested | 1 | 2 | 4 | 10 |
| --- | --- | --- | --- | --- |
| 1 | 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 2 | 2 |
| 4 | 1 | 2 | 4 | 4 |
The default of `10` therefore means "one per rank" for any run below 10
ranks — a 4-rank run writes 4 subfiles whatever you ask for. The knob is
only useful downwards: lower it to concentrate output into fewer, larger
files when a filesystem dislikes many concurrent writers.
Use fields_to_output deliberately. A large list is convenient for diagnostics but increases file size and I/O cost. Common field groups are:
| Field group | Examples |
|---|---|
| Base state | thbar, pibar, rhobar, rhobar_up |
| Dynamics | u, v, w, th, xi, eta, zeta |
| Moisture/P3 | qv, qc, qr, qi, qm, nc, nr, ni, bm |
| Radiation | sw_heating, lw_heating, swdn, lwdn, lwup, swup_toa, swdn_toa, lwup_toa, lwdn_toa, swup_sfc, swdn_sfc, lwup_sfc, lwdn_sfc |
| Surface/land | Tg, sfc_flux_th, sfc_flux_qv, sfc_flux_u, sfc_flux_v, le, hfx, st1, st2, st3, st4, gfx, topo |
dynamics
dynamics.solver
| Key | Type | Default | Meaning |
|---|---|---|---|
w_solver_method |
string | required | Vertical velocity solver: tridiagonal for the original method, jacobi for the 3D-parallel iteration path. |
iteration |
int | required | Fixed iteration count for the iterative solver path. |
WRXMU |
real | required | Relaxation/control parameter used by the wind solver. |
The solver settings are required. This is the small-case starting point used by the shipped examples:
{
"dynamics": {
"solver": {
"w_solver_method": "tridiagonal",
"iteration": 200,
"WRXMU": 2.5e-7
}
}
}
dynamics.forcings.sponge_layer
Damps selected fields above sponge_layer_base.
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | false |
Turns sponge-layer forcing on. |
damp_thermo |
bool | true |
Damp thermodynamic variables. |
damp_vort |
bool | true |
Damp vorticity variables. |
sponge_layer_base |
real | -1 |
Height in meters where damping begins. |
inv_CRAD |
real | -1.0 |
Inverse damping timescale used to build the damping coefficient. |
dynamics.forcings.random_perturbation
Useful for triggering convection in otherwise smooth initial states.
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | false |
Turns random forcing on. |
time_s |
real | 50.0 |
Apply perturbations until this simulated time. |
amplitude |
real | 1.0 |
Perturbation magnitude. |
z_start_m, z_end_m |
real | 0 |
Vertical layer where perturbations are applied. |
random_seed |
int | 12345 |
Seed for deterministic perturbations. A seed, timestep, and global cell coordinate always produce the same value, independent of scheduling and MPI decomposition. |
Copy this block to make the perturbation settings explicit. Leave enable
false for the model default, or turn it on and adjust only the layer, duration,
amplitude, and seed.
{
"dynamics": {
"forcings": {
"random_perturbation": {
"enable": false,
"time_s": 50.0,
"amplitude": 1.0,
"z_start_m": 0.0,
"z_end_m": 0.0,
"random_seed": 12345
}
}
}
}
dynamics.forcings.lateral_boundary_nudging
Relaxes selected variables toward large-scale forcing near selected boundaries.
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | false |
Turns nudging on. |
boundaries.west, .east, .south, .north |
bool | false |
Which boundaries are nudged. |
tau_b |
real | 300.0 |
Nudging timescale in seconds. |
offset |
real | 2500.0 |
Distance from the boundary at which the nudging zone starts, in meters. |
width |
real | 600.0 |
Width of the nudging zone, in meters. |
radius |
real | 2500.0 |
Corner-taper radius, in meters. |
target_vars |
list | ["th", "qv"] |
Variables to nudge. |
forcing_data.time_varying |
bool | false |
Select forcing files by time using file_prefix and update_interval_s instead of using one fixed file. |
forcing_data.directory |
string | "../rundata/LS_forcings/" |
Directory containing large-scale forcing files. |
forcing_data.file_name_for_not_varying |
string | "ls_forcing_constant.nc" |
File used when forcing is constant in time. |
forcing_data.file_prefix |
string | "ls_forcing_" |
Prefix for time-varying forcing files. |
forcing_data.update_interval_s |
real | 3600.0 |
Time spacing between time-varying forcing files. |
dynamics.forcings.areamn
Stores and relaxes area-mean vorticity/wind reference quantities.
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | false |
Turns area-mean nudging on. |
uvtau |
real | 0.0 |
Relaxation timescale/control value. |
nudge_start_m |
real | 0.0 |
Height in meters where nudging starts. |
target_source |
string | "initial" |
Where the nudging target comes from: initial holds the initial-state area means, netcdf reads them from the forcing files. Any other value is an error. |
forcing_data.directory |
string | required when target_source is netcdf |
Directory containing the forcing files. |
forcing_data.file_prefix |
string | "ls_forcing_" |
Prefix for the forcing files. |
forcing_data.update_interval_s |
real | 3600.0 |
Time spacing between forcing files. Must be positive. |
Copy this complete default forcing block when you want every forcing setting to
be explicit. All forcings remain off until their individual enable key is set
to true.
{
"dynamics": {
"forcings": {
"sponge_layer": {
"enable": false,
"damp_thermo": true,
"damp_vort": true,
"sponge_layer_base": -1.0,
"inv_CRAD": -1.0
},
"random_perturbation": {
"enable": false,
"time_s": 50.0,
"amplitude": 1.0,
"z_start_m": 0.0,
"z_end_m": 0.0,
"random_seed": 12345
},
"lateral_boundary_nudging": {
"enable": false,
"boundaries": {
"west": false, "east": false, "south": false, "north": false
},
"tau_b": 300.0,
"offset": 2500.0,
"width": 600.0,
"radius": 2500.0,
"target_vars": ["th", "qv"],
"forcing_data": {
"time_varying": false,
"directory": "../rundata/LS_forcings/",
"file_name_for_not_varying": "ls_forcing_constant.nc",
"file_prefix": "ls_forcing_",
"update_interval_s": 3600.0
}
},
"areamn": {
"enable": false,
"uvtau": 0.0,
"nudge_start_m": 0.0,
"target_source": "initial"
}
}
}
}
dynamics.prognostic_variables
An object whose keys are field names. Each names the tendency terms that advance it and the schemes each term uses.
{
"dynamics": {
"prognostic_variables": {
"th": {
"tendency_terms": {
"advection": {
"enable": true,
"temporal_scheme": "AdamsBashforth2",
"spatial_scheme": "Takacs"
}
}
}
}
}
}
| Key | Type | Default | Meaning |
|---|---|---|---|
<var>.tendency_terms |
object | (none) | Terms to apply. Term names: advection, buoyancy, stretching, twisting, coriolis. An unknown name is an error. |
<var>.tendency_terms.<term>.enable |
bool | true |
Skip the term when false. A disabled term is reported as [Disabled] at startup. |
<var>.tendency_terms.<term>.spatial_scheme |
string | required | Takacs, MUSCL, or weno5. |
<var>.tendency_terms.<term>.temporal_scheme |
string | "AdamsBashforth2" |
AdamsBashforth2, ForwardEuler, or SSPRK2. |
<var>.tendency_terms.<term>.scheme_options |
object | (none) | Scheme-specific options; see below. |
Fields listed here are allocated whether or not they exist by default, so a typo creates a new, unused field rather than failing. Common prognostic variables are th, xi, eta, zeta, qv, qc, qr, qi, qm, nc, nr, ni, and bm. P3-related fields should be present when P3 is enabled.
Coriolis is a special case: it is enabled only when all three of xi, eta, and zeta set tendency_terms.coriolis.enable to true. Enabling it on one or two of them leaves it off.
Scheme pairing rules
Rejected combinations stop the run at startup rather than silently degrading:
| Spatial scheme | Requires | Allowed on |
|---|---|---|
Takacs |
— | any prognostic field and term |
MUSCL |
temporal_scheme: SSPRK2 |
advection of a thermodynamic scalar or configured tracer |
weno5 |
temporal_scheme: SSPRK2, grid.n_halo_cells >= 3, and advection as the field's only enabled term |
advection of a configured passive tracer |
SSPRK2 is only available with MUSCL or weno5.
scheme_options for MUSCL
| Key | Type | Default | Meaning |
|---|---|---|---|
limiter |
string | "vanLeer" |
The only supported limiter. |
lower_bound |
real | 0.0 |
Nonnegative floor applied by the limiter. |
max_cfl |
real | 0.9 |
CFL cap; must be greater than zero. |
Use MUSCL only for the advection of one thermodynamic scalar or configured
tracer. Its temporal scheme must be SSPRK2, and that field cannot have any
other enabled tendency. Merge this into a copied case; the grid block shows
the minimum halo requirement and must retain the case's other grid keys.
{
"grid": {
"n_halo_cells": 2
},
"dynamics": {
"prognostic_variables": {
"th": {
"tendency_terms": {
"advection": {
"enable": true,
"temporal_scheme": "SSPRK2",
"spatial_scheme": "MUSCL",
"scheme_options": {
"limiter": "vanLeer",
"lower_bound": 0.0,
"max_cfl": 0.9
}
}
}
}
}
}
}
scheme_options for WENO5
| Key | Type | Default | Meaning |
|---|---|---|---|
epsilon |
real | 1.0e-6 |
Nonlinear-weight epsilon; must be finite and positive. No other key is accepted here. |
WENO5 is only for passive-tracer advection. It requires SSPRK2, no other
enabled tendency for that tracer, and at least three halo cells. Each MPI rank
also needs at least three physical x and y cells when those directions have
more than one global cell.
{
"grid": {
"n_halo_cells": 3
},
"dynamics": {
"tracers": {
"tracer1": {
"enable": true,
"tendency_terms": {
"advection": {
"enable": true,
"temporal_scheme": "SSPRK2",
"spatial_scheme": "weno5",
"scheme_options": {
"epsilon": 1.0e-6
}
}
}
}
}
}
}
The WENO5 coefficients assume uniform spacing, so only the uniform horizontal x and y directions use WENO reconstruction. Vertical tracer transport retains the existing Takacs scheme, including its stretched-grid metric and boundary handling. The default epsilon is the reference value used for regression testing; because it is dimensional, simulations with very different tracer magnitudes or floating-point precision may need to configure it. WENO5 is not available for vorticity or other dynamical-core advection.
dynamics.tracers
An object of passive tracers, each allocated as a 3-D field and advanced by the advection configuration given under the same key.
| Key | Type | Default | Meaning |
|---|---|---|---|
<name>.enable |
bool | true |
Skip the tracer entirely when false. |
<name>.source.enable |
bool | true when source is present |
Allocate a companion <name>_source tendency field, read from the spatial NetCDF file alongside the tracer itself. |
<name>.tendency_terms |
object | (none) | Same shape as a prognostic variable, but advection is the only supported term. |
Tracer names are validated against every field VVMex allocates and every name reserved by the initial-condition and output formats, and against internal suffixes (d_*, fe_tendency_*, *_m, *_ls). A collision is an error at startup, not a silent overwrite.
physics
Copy this default physics block, then enable only the packages needed by the
case. column_chunk_size is deliberately omitted: its default is every column
on the rank, so no fixed number is correct for all runs.
physics.p3
| Key | Type | Default | Meaning |
|---|---|---|---|
enable_p3 |
bool | false |
Enables P3 microphysics. |
make_lookup_table |
bool | false |
Generate the P3 lookup table instead of reading the shipped one. |
do_predict_nc |
bool | true |
Predict cloud droplet number concentration. |
do_prescribed_ccn |
bool | false |
Use prescribed CCN. |
max_total_ni |
real | 2000.0e3 |
Cap on total ice number concentration. |
physics.turbulence
| Key | Type | Default | Meaning |
|---|---|---|---|
enable_turbulence |
bool | false |
Enables the subgrid turbulence scheme, which produces RKM/RKH. |
physics.surface_process
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | false |
Enables the surface process wrapper. |
frequency_s |
real | 1 |
Surface/land/ocean call frequency in seconds. Should divide evenly by simulation.dt_s. |
land_scheme |
string | "none" |
none or noahlsm. noahlsm calls the Fortran Noah land model on land points. |
ocean_scheme |
string | "none" |
none, sflux_2d, sflux_tc_2d, or tco_ocean. |
Choosing sflux_2d or sflux_tc_2d uses the C++ surface-flux implementation for ocean points and disables the ocean part inside the land process. grid.vertical_coordinate_type: rcemip also relaxes the surface wind-speed floor from 1e-3 to 1.
physics.rrtmgp
| Key | Type | Default | Meaning |
|---|---|---|---|
enable_rrtmgp |
bool | false |
Enables RRTMGP radiation. When on, th additionally integrates a forward-Euler radiative tendency. |
rad_frequency_s |
real | 1.0 |
Radiation call frequency in seconds. Should divide evenly by simulation.dt_s. |
column_chunk_size |
int | all columns on the rank | Columns processed per chunk. Larger is usually faster but uses more memory; tune with domain size and rank count. |
pool_size_multiplier |
real | 1.0 |
Scales the radiation memory pool. |
active_gases |
list | ["h2o","co2","o3","n2o","co","ch4","o2","n2"] |
Gases passed to RRTMGP. |
do_aerosol_rad |
bool | false |
Include aerosol optics. |
extra_clnsky_diag |
bool | false |
Extra clean-sky diagnostics. |
extra_clnclrsky_diag |
bool | false |
Extra clean-clear-sky diagnostics. |
Prescribed gas volume mixing ratios
Surface values, mol/mol. Used for any gas in active_gases that the model does not carry itself.
| Key | Default | Key | Default | |
|---|---|---|---|---|
co2vmr |
355.03e-6 |
o2vmr |
0.209 |
|
n2ovmr |
320e-9 |
n2vmr |
0.7906 |
|
ch4vmr |
1700e-9 |
f11vmr |
0.0 |
|
covmr |
1.0e-7 |
f12vmr |
0.0 |
|
o3vmr |
0.3017e-7 |
Sun and calendar
| Key | Type | Default | Meaning |
|---|---|---|---|
time.year, .month, .day, .hour, .minute, .second |
int | -9999 |
Calendar start time driving the solar cycle. -9999 leaves the component unset. Note time.hour is also read by the output layer (defaulting to 16 there) to derive the GrADS start hour as (hour + 8) % 24. |
orbital_eccentricity |
real | -9999.0 |
Override Earth's orbital eccentricity. Values below zero mean "use the default orbit". |
orbital_obliquity |
real | -9999.0 |
Override the obliquity. |
orbital_mvelp |
real | -9999.0 |
Override the moving vernal equinox longitude of perihelion. |
fixed_total_solar_irradiance |
real | -9999.0 |
When positive, prescribes an invariant TOA solar constant (W m⁻²) instead of the orbital one. For idealized experiments such as RCE. |
fixed_solar_zenith_angle |
real | -9999.0 |
When positive, this value is used directly as the cosine of the solar zenith angle for every column, bypassing the orbital calculation. |
{
"physics": {
"p3": {
"enable_p3": false,
"make_lookup_table": false,
"do_predict_nc": true,
"do_prescribed_ccn": false,
"max_total_ni": 2000000.0
},
"turbulence": { "enable_turbulence": false },
"surface_process": {
"enable": false,
"frequency_s": 1.0,
"land_scheme": "none",
"ocean_scheme": "none"
},
"rrtmgp": {
"enable_rrtmgp": false,
"rad_frequency_s": 1.0,
"pool_size_multiplier": 1.0,
"active_gases": ["h2o", "co2", "o3", "n2o", "co", "ch4", "o2", "n2"],
"co2vmr": 0.00035503,
"o2vmr": 0.209,
"n2ovmr": 3.2e-7,
"n2vmr": 0.7906,
"ch4vmr": 1.7e-6,
"f11vmr": 0.0,
"f12vmr": 0.0,
"covmr": 1.0e-7,
"o3vmr": 3.017e-8,
"time": {
"year": -9999, "month": -9999, "day": -9999,
"hour": -9999, "minute": -9999, "second": -9999
},
"orbital_eccentricity": -9999.0,
"orbital_obliquity": -9999.0,
"orbital_mvelp": -9999.0,
"fixed_total_solar_irradiance": -9999.0,
"fixed_solar_zenith_angle": -9999.0
}
}
}
optimization
| Key | Type | Default | Meaning |
|---|---|---|---|
cuda_graph_halo_exchange |
list | (none) | Fields whose halo exchange is captured into a CUDA graph, e.g. ["u", "w", "xi", "eta", "zeta", "th"] plus hydrometeors. Ignored on CPU builds. |
Only include fields that exist in the current state and are exercised by the run. If you disable a physics package, remove its fields from the list unless the code still allocates them for your case.
performance.timing
Controls the built-in timing instrumentation. All optional.
| Key | Type | Default | Meaning |
|---|---|---|---|
enable |
bool | true |
Collect timers at all. |
warmup_steps |
int | 0 |
Skip this many steps before any timer records, so JIT, first-touch allocation and graph capture do not land in the averages. |
fence_gpu |
bool | false |
Fence the device around each timed region. Gives correct per-region GPU times at the cost of removing asynchrony — use it for attribution, not for headline throughput numbers. |
print_interval_steps |
int | 0 |
Print the timing report every N steps. 0 prints only at the end of the run. |
reset_after_interval_print |
bool | false |
Zero the accumulators after each interval print, so each report covers only the interval rather than the run so far. |
Copy this block when you need explicit timing controls:
{
"performance": {
"timing": {
"enable": true,
"warmup_steps": 0,
"fence_gpu": false,
"print_interval_steps": 0,
"reset_after_interval_print": false
}
}
}
constants
| Key | Type | Default | Meaning |
|---|---|---|---|
gravity |
real | required | Gravitational acceleration. |
Rd |
real | required | Dry-air gas constant. |
Cp |
real | required | Heat capacity at constant pressure. |
Lv |
real | required | Latent heat of vaporization. |
P0 |
real | required | Reference pressure. |
PI |
real | required | Pi. |
OMEGA |
real | 7.292e-5 |
Earth rotation rate, used by the default latitude-dependent Coriolis parameter. |
Coriolis on an f- or beta-plane
Present constants.coriolis_parameter and the latitude-dependent formula is replaced by a plane approximation, f = f0 + beta * (y - y_ref). Absent, the sphere formula using OMEGA is used, so existing configurations are unchanged.
| Key | Type | Default | Meaning |
|---|---|---|---|
coriolis_parameter |
real | (absent) | f0. Its presence is what switches on the plane approximation. |
coriolis_beta |
real | 0.0 |
Meridional gradient of f. Left at zero this is an f-plane. |
coriolis_reference_y_m |
real | domain centre | y_ref, in meters. |
Change constants only for controlled sensitivity experiments.
These are the required constants and the default Earth rotation rate. Copy the block only when creating a case from scratch; ordinary cases should retain the values already supplied by the chosen default case.
{
"constants": {
"gravity": 9.806,
"Rd": 287.04,
"Cp": 1004.5,
"Lv": 2500000.0,
"P0": 100000.0,
"PI": 3.14159265,
"OMEGA": 7.292e-5
}
}
Keys that look real but are not read
These appear in some shipped sample configurations and have no effect. They are listed so you do not spend time tuning them:
| Key | Status |
|---|---|
output.enable_netcdf |
Never read. Output engine selection is output.engine alone. |
optimization.cuda_graph_solver |
Never read. Only optimization.cuda_graph_halo_exchange exists. |
constants.PSFC |
Never read. A PSFC parameter view is allocated but nothing assigns it from the configuration. Surface pressure comes from the sounding profile. |
Consistency checklist
Before submitting a long run, check:
physics.rrtmgp.rad_frequency_s,physics.surface_process.frequency_s, andsimulation.output_interval_sare sensible multiples ofsimulation.dt_s.- Every
output.fields_to_outputname is allocated by the selected dynamics/physics configuration. - If
output.engineisSST, submit withsubmit.py --io N. If it isHDF5orBP5, omit--io. grid.n_halo_cellsis3if any tracer usesweno5.- If
restart.enableis true, the restart file storesmodel_time_s/model_step(or an elapsed-secondstime); otherwise setrestart.legacy_time_sexplicitly. The file name no longer affects the restart time. - The NetCDF variables listed in
netcdf_reader.variables_to_read.2dexist innetcdf_reader.source_file. - P3 hydrometeor variables are present in
dynamics.prognostic_variableswhenphysics.p3.enable_p3is true. - CUDA graph field lists match the fields actually allocated in the run.
- Optional keys you added are spelled exactly as in this page — a typo is silently ignored.
CMake and environment
Library paths and compilers are not set in this JSON file. Use CMakePresets.json and CMake cache variables for HDF5, NetCDF, PnetCDF, NVHPC, Kokkos, and MPI (see Quick Start).