This guide walks you through creating your first k-Wave simulation, introducing the four core components step by step.
Every k-Wave simulation requires exactly four components:
- Grid: Defines the computational domain
- Medium: Specifies material properties
- Source: Introduces acoustic energy
- Sensor: Records simulation data
Every k-Wave simulation is built from four core components that work together to define the acoustic problem:
.. grid:: 2
:gutter: 3
.. grid-item-card:: :doc:`Grid <get_started/grid_overview>`
:text-align: center
🕸️
Computational foundation defining spatial and temporal discretization
.. grid-item-card:: :doc:`Medium <get_started/medium_overview>`
:text-align: center
🌊
Material properties through which acoustic waves propagate
.. grid-item-card:: :doc:`Source <get_started/source_overview>`
:text-align: center
📡
How acoustic energy is introduced into the simulation
.. grid-item-card:: :doc:`Sensor <get_started/sensor_overview>`
:text-align: center
🎙️
Where and what acoustic data is recorded
Understanding these four components is key to mastering k-Wave simulations. Each component page provides conceptual explanations, practical examples, and API reference.
Let's build a simple 2D simulation to see how these work together.
The grid defines where and when we compute the acoustic fields:
from kwave import kWaveGrid
# Create a 2D grid: 2cm × 2cm domain with 100μm resolution
Nx, Ny = 200, 200 # 200 × 200 grid points
dx, dy = 100e-6, 100e-6 # 100 μm spacing
grid = kWaveGrid([Nx, Ny], [dx, dy])This grid (~100 μm spacing) is suitable up to about 7.5 MHz (≈2 points per wavelength in water). For higher frequencies, reduce dx to maintain ≥2–3 PPW. Step 2: Define the Medium -------------------------
The medium specifies how waves propagate through the material:
from kwave import kWaveMedium
# Simple water-like medium
medium = kWaveMedium(
sound_speed=1500, # m/s - speed of sound in water
density=1000 # kg/m³ - density of water
)For a homogeneous medium, we specify properties as single values that apply everywhere.
The source defines how acoustic energy enters the simulation:
import numpy as np
from kwave import kSource
# Create initial pressure distribution (photoacoustic-style)
source = kSource()
# Simple circular initial pressure in the center
x_pos = grid.x_vec
y_pos = grid.y_vec
X, Y = np.meshgrid(x_pos, y_pos, indexing='ij')
# 2mm radius circle with 10 kPa initial pressure
radius = 2e-3 # 2 mm
center_x, center_y = 0, 0 # Center of domain
initial_pressure = np.zeros(grid.N)
mask = (X - center_x)**2 + (Y - center_y)**2 <= radius**2
initial_pressure[mask] = 10e3 # 10 kPa
source.p0 = initial_pressureThis creates an initial pressure distribution that will propagate outward as acoustic waves.
Sensors specify where we record the acoustic data:
from kwave import kSensor
# Create sensors around the edge to capture the expanding wave
sensor_mask = np.zeros(grid.N)
sensor_mask[0, :] = 1 # Top edge
sensor_mask[-1, :] = 1 # Bottom edge
sensor_mask[:, 0] = 1 # Left edge
sensor_mask[:, -1] = 1 # Right edge
sensor = kSensor(mask=sensor_mask, record=['p'])Now we combine all four components and run:
from kwave.kspaceFirstOrder import kspaceFirstOrder
# Run with the NumPy/CuPy backend in Python
sensor_data = kspaceFirstOrder(
grid, medium, source, sensor,
pml_inside=False,
quiet=True,
)Note
kspaceFirstOrder() is the unified entry point introduced in v0.6.0.
It auto-detects dimensionality from the grid and replaces the legacy
kspaceFirstOrder2D / 3D functions. See :doc:`/get_started/new_api`
for details.
The legacy functions still work but emit warnings.
import matplotlib.pyplot as plt
# Plot the recorded pressure at sensors vs time
plt.figure(figsize=(10, 6))
plt.imshow(sensor_data['p'], aspect='auto', extent=[
0, grid.Nt * grid.dt * 1e6, # Time in μs
0, sensor_data['p'].shape[0] # Sensor number
])
plt.xlabel('Time (μs)')
plt.ylabel('Sensor Number')
plt.title('Recorded Pressure at Boundary Sensors')
plt.colorbar(label='Pressure (Pa)')
plt.show()- The initial pressure distribution creates acoustic waves
- These waves propagate outward through the medium at 1500 m/s
- When waves reach the boundary sensors, pressure is recorded
- The result shows the acoustic wavefront arriving at different sensors over time
Now that you understand the four-component structure, explore these examples to see how the same framework applies to different applications:
Beginner Examples (start here):
- :ghfile:`Photoacoustic Waveforms <examples/legacy/ivp_photoacoustic_waveforms/README.md>` - See how 2D and 3D wave propagation differs
- :ghfile:`Defining Transducers <examples/legacy/us_defining_transducer/README.md>` - Learn about ultrasound transducers
Medical Imaging Applications:
- :ghfile:`B-mode Linear Transducer <examples/legacy/us_bmode_linear_transducer/README.md>` - Full B-mode ultrasound imaging pipeline
- :ghfile:`2D FFT Line Sensor <examples/legacy/pr_2D_FFT_line_sensor/README.md>` - Photoacoustic image reconstruction
Advanced Transducer Modeling:
- :ghfile:`Array as Source <examples/legacy/at_array_as_source/README.md>` - Complex array transducers without staircasing
- :ghfile:`Focused Bowl 3D <examples/legacy/at_focused_bowl_3D/README.md>` - Focused ultrasound applications
Acoustic Field Analysis:
- :ghfile:`Beam Patterns <examples/legacy/us_beam_patterns/README.md>` - Understand beam formation and focusing
- :ghfile:`Focused Detector 2D <examples/legacy/sd_focussed_detector_2D/README.md>` - Sensor directivity effects
Each example builds on the same four-component framework but demonstrates different aspects of acoustic simulation. The key insight is that no matter how complex the application, every k-Wave simulation follows this same logical structure.