Unified API (v0.6.0)¶
Starting with v0.6.0, kspaceFirstOrder() is the preferred way to run
simulations. It replaces the legacy kspaceFirstOrder2D,
kspaceFirstOrder3D, and their GPU variants with a single function that
auto-detects dimensionality from the grid.
Quick Start¶
from kwave.kgrid import kWaveGrid
from kwave.kmedium import kWaveMedium
from kwave.ksource import kSource
from kwave.ksensor import kSensor
from kwave.kspaceFirstOrder import kspaceFirstOrder
import numpy as np
# Setup (works for 1D, 2D, or 3D — just change grid dimensions)
kgrid = kWaveGrid([128, 128], [0.1e-3, 0.1e-3])
kgrid.makeTime(1500)
medium = kWaveMedium(sound_speed=1500, density=1000)
source = kSource()
source.p0 = np.zeros((128, 128))
source.p0[64, 64] = 1.0
sensor = kSensor(mask=np.ones((128, 128), dtype=bool))
# Run with the NumPy/CuPy solver in Python
result = kspaceFirstOrder(kgrid, medium, source, sensor)
print(result["p"].shape) # (16384, Nt) — time series at each sensor
print(result["p_final"].shape) # (128, 128) — final pressure field
Backend and Device¶
Two independent choices control how the simulation runs:
backend selects the simulation engine:
"python"(default) — pure Python solver using NumPy or CuPy. No external dependencies beyond NumPy."cpp"— serializes to HDF5 and invokes the pre-compiled C++ binary. Requires FFTW (brew install fftwon macOS).
device selects the hardware:
"cpu"(default) — NumPy forbackend="python", OMP binary forbackend="cpp"."gpu"— CuPy forbackend="python"(requires CuPy + CUDA), CUDA binary forbackend="cpp".
# NumPy on CPU (default)
result = kspaceFirstOrder(kgrid, medium, source, sensor)
# CuPy on GPU (requires CuPy + CUDA)
result = kspaceFirstOrder(kgrid, medium, source, sensor, device="gpu")
# C++ binary on CPU (requires FFTW)
result = kspaceFirstOrder(kgrid, medium, source, sensor, backend="cpp")
# C++ CUDA binary on GPU
result = kspaceFirstOrder(kgrid, medium, source, sensor, backend="cpp", device="gpu")
PML Options¶
The perfectly-matched layer (PML) absorbs outgoing waves at the domain boundary. Three controls:
# Fixed size (default: 20 grid points on all sides)
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_size=20)
# Per-dimension sizes
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_size=(10, 15))
# Auto-optimal size (computed from grid via FFT analysis)
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_size="auto")
# PML inside the user domain (saves memory, but PML overlaps your grid)
result = kspaceFirstOrder(kgrid, medium, source, sensor, pml_inside=True)
By default (pml_inside=False), the grid is automatically expanded so
the PML sits outside your domain. Full-grid output fields (_final,
_max, etc.) are cropped back to the original size.
Save-Only Mode (Cluster Submission)¶
Generate HDF5 input files for the C++ binary without running it:
result = kspaceFirstOrder(
kgrid, medium, source, sensor,
backend="cpp",
save_only=True,
data_path="/path/to/output",
)
print(result["input_file"]) # path to HDF5 input
print(result["output_file"]) # path where C++ will write results
Full Parameter Reference¶
- kspaceFirstOrder(kgrid, medium, source, sensor=None, *, pml_size=20, pml_alpha=2.0, pml_inside=False, use_sg=True, use_kspace=True, smooth_p0=True, backend='python', device='cpu', save_only=False, data_path=None, quiet=False, debug=False, num_threads=None, device_num=None)[source]¶
Run a k-Wave simulation.
Unified entry point replacing the legacy kspaceFirstOrder2D / 3D functions. Works with 1-D, 2-D, and 3-D grids.
- Parameters:
kgrid (kWaveGrid) – Simulation grid (defines dimensionality, spacing, and time steps).
medium (kWaveMedium) – Acoustic medium properties (sound speed, density, absorption, nonlinearity).
source (kSource) – Pressure and/or velocity source terms.
sensor (kSensor | NotATransducer | None) – Sensor mask defining where the field is recorded.
Nonerecords the entire grid.pml_size (int | tuple | str)
pml_alpha (float | tuple)
pml_inside (bool)
use_sg (bool)
use_kspace (bool)
smooth_p0 (bool)
backend (str)
device (str)
save_only (bool)
data_path (str | None)
quiet (bool)
debug (bool)
num_threads (int | None)
device_num (int | None)
- Keyword Arguments:
pml_size – Perfectly-matched-layer thickness in grid points. A scalar applies to all dimensions; a tuple sets each dimension independently.
"auto"selects an optimal size via FFT-based analysis. Default20.pml_alpha – PML absorption coefficient (Nepers per grid point). Scalar or per-dimension tuple. Default
2.0.pml_inside – When
False(default), the grid is automatically expanded by2 * pml_sizeso the PML sits outside the user domain; full-grid output fields (_final,_max, etc.) are cropped back to the original size. WhenTrue, the PML occupies the outermost grid points of the user-supplied grid, which saves memory but means PML absorption will modify field values near the domain boundary.use_sg – Use a staggered grid for velocity fields. Default
True.use_kspace – Apply the k-space correction to the time-stepping scheme. Default
True.smooth_p0 – Smooth the initial pressure distribution to suppress staircasing artifacts. Default
True.backend – Simulation engine.
"python"runs a pure-Python / NumPy / CuPy solver;"cpp"serializes to HDF5 and invokes the compiled C++ binary. Default"python".device –
"cpu"or"gpu". Forbackend="python"this selects NumPy (cpu) vs CuPy (gpu). Forbackend="cpp"it selects the OMP vs CUDA binary. Default"cpu".save_only – When
True(backend="cpp"only), write the HDF5 input file and return without running the binary. Useful for cluster submission. DefaultFalse.data_path – Directory for HDF5 input/output files (
backend="cpp"only). IfNonea temporary directory is created and cleaned up automatically after the run. Set explicitly to inspect or reuse the HDF5 files. DefaultNone.quiet – Suppress progress output. Default
False.debug – Print detailed diagnostic output. Default
False.num_threads – Thread count for the C++ OMP binary.
Noneuses all available cores. DefaultNone.device_num – GPU device index for CUDA execution. Default
None.
- Returns:
Recorded sensor data keyed by field name (e.g.
"p","p_final","ux","uy").All time-series are
(n_sensor, Nt)with sensor points in C-flattened order. Usereshape_to_grid()to recover spatial structure for full-grid masks.- Return type:
dict
Migrating from Legacy API¶
The kwave.compat module provides options_to_kwargs() to convert
old SimulationOptions / SimulationExecutionOptions to keyword
arguments:
from kwave.compat import options_to_kwargs
from kwave.options.simulation_options import SimulationOptions
from kwave.options.simulation_execution_options import SimulationExecutionOptions
sim_opts = SimulationOptions(smooth_p0=False, pml_inside=True)
exec_opts = SimulationExecutionOptions(is_gpu_simulation=False)
kwargs = options_to_kwargs(simulation_options=sim_opts, execution_options=exec_opts)
result = kspaceFirstOrder(kgrid, medium, source, sensor, **kwargs)
The legacy kspaceFirstOrder2D and kspaceFirstOrder3D functions
continue to work but emit FutureWarning.