Elastic propagator reference¶
The elastic propagators – elastic, elastic_born and elastic_vti – in both their Module class and functional forms. Usage covers the conventions they share with every other propagator, and Elastic wave equation, Born Modelling with the Elastic Wave Equation and Elastic VTI (anisotropic) wave equation cover the physics.
Elastic Class¶
- class deepwave.Elastic(lamb: Tensor, mu: Tensor, buoyancy: Tensor, grid_spacing: float | Sequence[float], *, requires_grad: bool | Sequence[str] | None = None, lamb_requires_grad: bool | None = None, mu_requires_grad: bool | None = None, buoyancy_requires_grad: bool | None = None, storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None)¶
A PyTorch Module for elastic wave propagation.
Stability: stable (see Stability policy).
This Module provides a convenient way to perform elastic wave propagation, storing the Lamé parameters (lamb and mu), the buoyancy (buoyancy) and grid_spacing once, so that each
forward()call needs only the arguments that vary between calls.Deepwave orders spatial dimensions from slowest-varying to fastest-varying and attaches no physical meaning to any of them; the component suffixes count from the fastest axis, so a 2-D run uses
_yand_xand a 3-D run uses_z,_yand_x. See Dimension order and the axis convention.- Parameters:
lamb – The first Lamé parameter model, lambda, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.mu – The second Lamé parameter model, mu, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.buoyancy – The buoyancy (1/density) model. A cell with
buoyancy = 0is a vacuum, not an infinitely dense cell; see the vacuum sentinel in Boundary conditions, which also explains how the sentinel is averaged onto the staggered nodes. It is of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.grid_spacing – The spatial grid cell size. It can be a single number (for isotropic grids) or a sequence of numbers (for anisotropic grids).
requires_grad – Which of this module’s models require a gradient.
None(the default) defers entirely to the individual<model>_requires_gradflags below, each of which is unset (None) by default and then meansFalse.Trueselects every model this module owns,Falseselects none, and a sequence of model names selects exactly those. Passing it together with an individual flag that was given explicitly raisesValueErrorrather than letting one silently win – whichever way the two point, and even when they agree, so that there is one rule rather than a direction-dependent one.lamb_requires_grad – A bool specifying whether gradients should be computed for lamb. Unset by default, which means False. Cannot be combined with requires_grad.
mu_requires_grad – A bool specifying whether gradients should be computed for mu. Unset by default, which means False. Cannot be combined with requires_grad.
buoyancy_requires_grad – A bool specifying whether gradients should be computed for buoyancy. Unset by default, which means False. Cannot be combined with requires_grad.
storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated.
storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated.
storage_compression – Lossy: it changes the model gradient, by about 0.2-4% in 2-D and 0.2-8% in 3-D in relative L2 error. The name does not say so, which is why this entry does. If True, the sampled wavefield history kept for the model gradient is stored as 8-bit block max-abs quantisation (8 cells per spatial dimension per block, one full-precision scale per block). Measured relative L2 error against an uncompressed run: about 0.2-4% for 2-D problems and 0.2-8% for 3-D. For a matched geometry 3-D is consistently two to five times the 2-D error – a 3-D block shares one scale across 512 cells against 64 in 2-D – but the spread across geometries and loss functions is wide enough that the two ranges overlap. The error does not grow with the size of the problem: with the survey and the model anomaly held at fixed cell indices it is constant to five significant figures from 32x32 to 400x400 and from 32^3 to 120^3, and constant in nt once the record is long enough for the wavefield to reach the receivers. It does depend on the survey geometry and on the loss function – one fixed 3-D problem gives 3.4% under a sum of squared receiver amplitudes and 1.9% under a data residual – so treat these as ranges rather than a number to budget against. A barely illuminated gradient is the exception: a record too short for the wavefield to reach the receivers at all can give tens of percent, because there the gradient itself is nearly empty. The relative maximum error, defined as max|g_comp - g_exact| / max|g_exact|, is comparable to the relative L2 error rather than a fixed multiple of it – typically between 0.3 and 3 times it, and in 3-D more often below the L2 error than above. Do not use a per-cell relative error as a figure of merit: it is unbounded near the gradient’s zero crossings. The error is essentially independent of dtype (float32 and float64 agree to three or four significant figures) and exactly independent of storage_mode. The worst-affected values are the outermost cells of the model: a cell’s gradient there sums large, largely cancelling contributions from the absorbing layer, so the quantisation error does not cancel with them. Measured on the gradient of scalar_born’s dv, normalised by the gradient’s own maximum, the largest edge-cell error is 0.03-0.07 in 1-D, about 1e-4 in 2-D and about 1e-5 in 3-D, against below 1e-3, 2e-5 and 1e-5 respectively in the interior. Disabling compression removes quantisation error; it does not remove model-gradient sampling error. Exact discrete model derivatives also require an effective history stride of one and fixed setup parameters (see What Deepwave guarantees about gradients). Unaffected, bit for bit: the returned wavefields and auxiliary state, the receiver amplitudes, and the gradients with respect to the source amplitudes and the initial wavefields – compression touches only the stored history that forms the model gradient. Do not use it for `gradcheck`, adjoint or dot-product tests, or publication-quality gradients. In exchange it shrinks the offloaded host buffer by close to the size of the dtype in bytes – each cell becomes one byte, plus one full-precision scale per block – which is about 3.8x in 2-D and 4.0x in 3-D for float32, and about 7.1x and 7.9x for float64. That ratio is set by the dtype and the number of spatial dimensions, not by the size of the problem. Composed with storage_mode=”cpu” it runs roughly 2 to 3 times faster than uncompressed offload, because it reduces the PCIe traffic that offload is bottlenecked on. Defaults to False.
- Model ownership and gradients
Every model tensor given to the constructor is wrapped in a new
torch.nn.Parameterthat this module owns. The Parameter is a distinct leaf tensor that shares storage with the tensor you passed in: it is not a copy, so an in-place edit of one is visible in the other, but it is not the same object. Gradients therefore accumulate on the module’s own attribute (module.<model>.grad) and never on the tensor you passed in. A model requires a gradient only if you ask for one, through the constructor’srequires_gradargument or by callingmodule.<model>.requires_grad_(True)afterwards; handmodule.parameters()to atorch.optimoptimiser as usual. An optional model left asNoneis not a Parameter at all, so it appears in neitherparameters()norstate_dict(); assigning a tensor to that attribute later stores a plain tensor rather than registering a Parameter, so it stays out ofparameters()andstate_dict()(and out of any checkpoint) – give the model to the constructor, or wrap it yourself intorch.nn.Parameter. Because the module owns a leaf Parameter, it cannot carry an upstream autograd graph: if the model is itself produced by another operation – a network mapping a latent vector to a wavespeed, a reparameterisation, a smoothing filter – wrapping it in a module severs that graph and no gradient reaches the producer. Use the functional interface for anything graph-producing; it takes the model as an ordinary tensor argument and backpropagates through it.
Initialises the Module.
- forward(dt: float, *, sources: Mapping[str, tuple[Tensor, Tensor | Hicks] | tuple[Tensor, Tensor | Hicks, Tensor | None]] | None = None, receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, source_amplitudes_pressure_rate: Tensor | None = None, source_amplitudes_p: Tensor | None = None, source_amplitudes_z: Tensor | None = None, source_amplitudes_y: Tensor | None = None, source_amplitudes_x: Tensor | None = None, source_locations_pressure_rate: Tensor | Hicks | None = None, source_locations_p: Tensor | Hicks | None = None, source_locations_z: Tensor | Hicks | None = None, source_locations_y: Tensor | Hicks | None = None, source_locations_x: Tensor | Hicks | None = None, source_mask_pressure_rate: Tensor | None = None, source_mask_z: Tensor | None = None, source_mask_y: Tensor | None = None, source_mask_x: Tensor | None = None, receiver_locations_p: Tensor | Hicks | None = None, receiver_locations_z: Tensor | Hicks | None = None, receiver_locations_y: Tensor | Hicks | None = None, receiver_locations_x: Tensor | Hicks | None = None, receiver_mask_p: Tensor | None = None, receiver_mask_z: Tensor | None = None, receiver_mask_y: Tensor | None = None, receiver_mask_x: Tensor | None = None, vz_0: Tensor | None = None, vy_0: Tensor | None = None, vx_0: Tensor | None = None, sigmazz_0: Tensor | None = None, sigmayz_0: Tensor | None = None, sigmaxz_0: Tensor | None = None, sigmayy_0: Tensor | None = None, sigmaxy_0: Tensor | None = None, sigmaxx_0: Tensor | None = None, initial_state: PropagatorOutput | Mapping[str, Tensor | AuxiliaryState] | None = None, accuracy: Literal[2, 4, 6, 8] = 4, pml_width: int | Sequence[int] = 20, boundary: str | Sequence[str] | None = None, pml_freq: float | None = None, mpml_fraction: float = 0.0, surface_method: Literal['ivm', 'pm'] = 'ivm', max_vel: float | None = None, courant_number: float | None = None, survey_pad: int | Sequence[int | None] | None = None, origin: Sequence[int] | None = None, nt: int | None = None, model_gradient_sampling_interval: int = 1, checkpoint_segments: int | None = None, freq_taper_frac: float = 0.0, time_pad_frac: float = 0.0, time_taper: bool = False, check_output_finite: bool = True, forward_callback: Callback | None = None, backward_callback: Callback | None = None, callback_frequency: int = 1, backend: str = 'auto', python_backend: Literal['eager', 'jit', 'compile'] | bool | None = None, storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None, location_interpolation: Literal['auto', 'hicks', 'none'] = 'auto', location_interpolation_halfwidth: int = 4) PropagatorOutput¶
Perform forward propagation/modelling.
See
elastic()for details (the constructor-owned lamb/mu/ buoyancy/grid_spacing and the storage settings are supplied from the stored module state).- Parameters:
dt – The time step interval of the input and output (internally a smaller interval may be used in propagation to obey the CFL (Courant-Friedrichs-Lewy) condition for stability). Due to the staggered time grid, stress-related fields (including pressure) are at integer time steps t*dt, while velocity-related fields are at half time steps (t-0.5)*dt. Deepwave is unit-agnostic: choose any single consistent system of units for
lamb,mu,buoyancy,grid_spacing, anddt; see Units and source conventions.sources – This simulation’s sources, keyed by channel. This is the canonical way to specify a survey. Each value is
(amplitudes, locations), or(amplitudes, locations, mask)to include an activity mask. The channels arepressure_rate,z,y,x(zonly in 3-D,yonly in 2-D and 3-D);pis a deprecated spelling ofpressure_ratehere. Exactly equivalent to the flatsource_amplitudes_*/source_locations_*keywords, which remain permanently supported; giving one channel in both forms raises. Optional.receivers – This simulation’s receivers, keyed by channel, as the canonical alternative to the flat
receiver_locations*keywords. Each value is a locations object, or(locations, mask)to include an activity mask. The channels arep,z,y,x(zonly in 3-D,yonly in 2-D and 3-D). Giving one channel in both forms raises. Optional.source_amplitudes_pressure_rate – A Tensor with dimensions [shot, source, time] of pressure rates, with units of pressure/time (a positive amplitude is compressional). This differs from the acoustic family, whose
source_amplitudes_volume_rateis a volume-injection rate; see Units and source conventions for the conversion. Each sample is added to the update from p(t*dt) to p((t+1)*dt), so it acts at (t+0.5)*dt, half a step after the pressure receiver of the same index is recorded. To drive the propagation with a volumetric (extended) source instead of hand-placed point sources, build the amplitudes and integer locations withdeepwave.wavefields.source_field_to_sources().source_amplitudes_p – Deprecated spelling of
source_amplitudes_pressure_rate, which means exactly the same thing. It warnsdeepwave.DeepwaveFutureWarningand will be removed in Deepwave 0.4.0: the letterpnames a pressure rate here and a volume rate on the acoustic family, two quantities that differ by roughly the bulk modulus, so a source channel says which one it injects; see Units and source conventions.premains the receiver channel’s name. Passing both raises. Optional.source_amplitudes_z – A Tensor with dimensions [shot, source, time] of force densities in the z direction, with units of force/volume in both 2-D and 3-D. Each sample is added to the update from vz((t-0.5)*dt) to vz((t+0.5)*dt), so it acts at t*dt, half a step after the velocity receiver of the same index is recorded. This channel exists only in 3-D.
source_amplitudes_y – A Tensor with dimensions [shot, source, time] of force densities in the y direction, with units of force/volume. Timed as
source_amplitudes_z.source_amplitudes_x – A Tensor with dimensions [shot, source, time] of force densities in the x direction, with units of force/volume. Timed as
source_amplitudes_z.source_locations_pressure_rate – A Tensor containing the locations of pressure sources. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_p – Deprecated spelling of
source_locations_pressure_rate, assource_amplitudes_pis ofsource_amplitudes_pressure_rate. Passing both raises. Optional.source_locations_z – A Tensor with dimensions [shot, source, ndim], containing the index in the ndim spatial dimensions of the cell that each source oriented in the z spatial dimension is located in, relative to the origin of the model. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_y – A Tensor containing the locations of sources oriented in the y spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_x – A Tensor containing the locations of sources oriented in the x spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_mask_pressure_rate – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
pressure_ratechannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_pressure_rateare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_pressure_rate, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_z – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_y – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
ychannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_x – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
xchannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_locations_p – A Tensor containing the coordinates of the pressure receivers. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_z – A Tensor with dimensions [shot, receiver, ndim], containing the coordinates of the cell containing each receiver oriented in the z spatial dimension. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_y – A Tensor containing the coordinates of the receivers oriented in the y spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_x – A Tensor containing the coordinates of the receivers oriented in the x spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.vz_0 – Initial vz (velocity in the z dimension) wavefield at time step -1/2. Like every initial wavefield, it may be provided either at the shape of the simulation domain (the extracted model region plus the PML), which is the shape a previous call returns, or at the shape of the extracted model region itself, which Deepwave zero-pads for you; see the wavefield_0 entry of
deepwave.scalar()for the full description.vy_0 – Initial vy (velocity in the y dimension) wavefield at time step -1/2.
vx_0 – Initial vx (velocity in the x dimension) wavefield at time step -1/2.
sigmazz_0 – Initial value for the zz component of the stress field at time step 0.
sigmayz_0 – Initial value for the yz component of the stress field at time step 0.
sigmaxz_0 – Initial value for the xz component of the stress field at time step 0.
sigmayy_0 – Initial value for the yy component of the stress field at time step 0.
sigmaxy_0 – Initial value for the xy component of the stress field at time step 0.
sigmaxx_0 – Initial value for the xx component of the stress field at time step 0.
initial_state –
An optional bundle of initial wavefields, supplied as either a
deepwave.PropagatorOutput(the return of a previous call), that output’s final_state mapping, or any mapping whose keys are the public state field names (vz_0, sigmazz_0, …) and auxiliary_state (adeepwave.AuxiliaryStatefrom a previous call). Each entry fills the correspondingly-named initial wavefield that was not also passed explicitly (matching is by name, so the public-vs-backend wavefield ordering is irrelevant), so a previous output can be passed back in to continue the simulation (its receiver_amplitudes_* fields are ignored), and it is the unambiguous route: the auxiliary state records the propagator, accuracy, PML width, boundary conditions, number of relaxation mechanisms, simulation-domain shape and internal time step it was produced with, so a continuation that does not match them raises rather than producing quiet nonsense, and one whose pml_freq or max_vel differs – which reshapes the absorbing boundary without changing what the tensors are – warns. The survey origin is recorded and reused: see the continuation rule below.Continuation rule. When initial_state carries a region – a PropagatorOutput from a previous call, whose RunInfo.origin and RunInfo.extent record the region that run used, or a AuxiliaryState carrying the same – and you pass neither survey_pad nor origin, that stored region is reused: the continuation propagates exactly the same part of the model, and the new call’s sources and receivers must lie inside it (they are checked; a location outside it raises). If you pass survey_pad or origin explicitly, your value wins and the stored wavefields must match the region it implies; a disagreement raises rather than silently re-windowing the simulation. Passing the previous call’s output (initial_state=out) is the unambiguous route. A mapping of bare tensors records no region at all, so it warns and assumes origin zero unless you pass origin.
The individual absorbing-boundary field names (m_vzz_0, …, m_sigmaxxx_0) are still accepted as keys, with a FutureWarning; they will stop being accepted in Deepwave 0.4.0. Providing a wavefield both here and as an explicit argument raises an error. For the continuation to exactly reproduce a single run over the combined time range, the same internal time step and the same absorbing boundary must be used throughout. The first holds when the user dt already satisfies the CFL condition (no internal sub-stepping); otherwise the segment boundary introduces a small discretisation difference. The second is automatic: when pml_freq or max_vel is omitted, the value recorded in initial_state is used, rather than one inferred from this call’s own portion of the source record or from its model, so the continuation builds the same absorbing boundary as the run it continues. Passing either explicitly overrides that, and a mismatch with the recorded value then warns; a mismatched internal time step raises. When a gradient will be taken, each call retains the initial wavefields it is given until its backward pass runs – the second-order (Hessian-vector-product) path replays the propagation from them – so a differentiable continuation loop holds one full wavefield set per iteration, and dropping your own reference to the previous output does not release it; run segments that do not need a gradient under
torch.no_grad(), or wrap segments intorch.utils.checkpoint.checkpointoverdeepwave.checkpointing.run_segments(), to bound the peak memory. If initial_state is a PropagatorOutput and neither origin nor survey_pad is also passed, the survey origin used to produce it is recovered automatically, so the continuation extracts the same region of the model rather than assuming an origin of zero.The number of shots (the leading dimension of every per-shot tensor) is taken from the source locations if any are given, otherwise from the initial wavefields. So a call with nt and no sources takes its shot count from the wavefields given here; with neither sources nor initial wavefields the call raises. Optional, default None.
accuracy – The finite difference order of accuracy. Possible values are 2, 4, 6, and 8, with larger numbers resulting in more accurate results but greater computational cost. Default 4.
pml_width –
A single number, or a sequence of numbers for each side, specifying the width (in number of cells) of the PML that prevents reflections from the edges of the model. If a single value is provided, it will be used for all edges. If a sequence is provided, it should contain values for the edges in the following order:
beginning of first dimension
end of first dimension
beginning of second dimension
end of second dimension
…
Larger values result in smaller reflections, with values of 10 to 20 being typical. For a reflective rigid surface, set the value for that edge to be zero. The wavespeed in the PML region is obtained by replicating the values on the edge of the model. Optional, default 20. A face whose
pml_widthis zero does not absorb: it becomes an implicit reflecting boundary whose type depends on the propagator and the field component. See Reflecting edges for the per-propagator reflection coefficient and surface location, and prefer naming the condition withboundary(ordeepwave.boundaries()), which also uses the exact image rather than this approximate one.boundary – An optional single string, applying to every face, or a list of 2 * ndim strings selecting a first-class flat-face boundary condition per face, in the same order as pml_width and with the same semantics as
deepwave.acoustic()’s boundary (“pml”, “free”, “rigid”, or “periodic”; a non-“pml” face requires pml_width == 0 on that face). This is a fast, flat-face image-method shortcut for the common case of a boundary lying exactly on a domain edge – it does not replace the improved vacuum method (IVM, see the buoyancy argument above), which remains the only way to represent an irregular or topographic free surface. The per-field parities (which of the stress-tensor and velocity components are imaged odd/even, and which need no imaging at all) are derived from Robertsson (1996)’s stress-image method and documented, with citations, in docs/boundaries.rst’s Policy section. Validated on both the eager (backend=”eager”) and the default compiled C/CUDA backends, against analytic reflection coefficients, against the improved vacuum method, and by gradient checking. Forward-mode AD (torch.func.jvp) and the compiled second-order (HVP) path – which route through elastic_born’s compiled backend – also support a non-“pml” face (elastic_born has its own bc-threaded compiled kernel). Availability: “pml” is accepted on every face at every accuracy, and “rigid” on the beginning of a dimension at every accuracy and on the end of a dimension at accuracy=2. “rigid” on the end of a dimension with accuracy >= 4, and “free” and “periodic” on any face, raisedeepwave.DeepwaveNotImplementedError: those guard-ring fills do not conserve a discrete energy, so the solution can grow without bound. Model a free surface with a vacuum layer (the improved vacuum method) instead; put a “rigid” face at the beginning of the dimension (flip the model along that axis), or use accuracy=2. Faces may be accepted in a later release; none is removed.pml_freq –
The frequency to use when constructing the PML, usually the dominant frequency of the source wavelet: the PML absorbs best near this frequency, and choosing it poorly makes the edges more reflective. Optional. If not specified, it is inferred from the peak of the source amplitudes’ spectrum (which returns the wavelet’s own centre frequency for a Ricker), or, if the simulation has no sources at all, from
0.5 / dt / 5, a fifth of the Nyquist frequency. Nothing is inferred when the call continues an earlier one: an omittedpml_freqthen takes the value recorded ininitial_state. The value actually used is reported asout.info.pml_freq. Pin it explicitly for any published result: leaving it inferred makes the absorbing boundary depend on the wavelet, so changing the wavelet also changes the boundary. The source-amplitude gradient does not follow that path, so pinpml_freqwhen you differentiate with respect to the source. See Choosing pml_freq.Note
Deepwave 0.0.27 and earlier used a fixed 25 Hz here. A seismic call with a 25 Hz wavelet therefore infers exactly 25.0 and gets the same numbers as before; a call whose inferred value is anything else warns once, naming
pml_freq=25.0as the line that restores the old behaviour. That warning is a migration aid and is removed in 0.4.0.mpml_fraction – The multiaxial PML (M-PML) cross-damping fraction, an opt-in stability option for elastic media. Inside each absorbing layer the standard PML damps only the direction normal to that layer’s face; with
mpml_fraction = pthe damping profile of that layer is also applied, scaled byp, to each of the other axes, so every axis in the layer is damped byptimes that layer’s own profile in addition to whatever its own layer contributes. This is the multiaxial PML of Meza-Fajardo and Papageorgiou (2008, https://doi.org/10.1785/0120070223), in which the same fraction is calledp. The default of 0 gives the standard CFS-C-PML, with behaviour and performance byte-identical to not having the feature. Elastic simulations that combine a thin region between two facing free surfaces with a high Poisson’s ratio and a perpendicular PML can suffer a slow exponential (late-time) instability, which a small positive value cures. The trade-off is that the M-PML is no longer perfectly matched, so the layer reflects more: on a homogeneous elastic half-space withpml_width=20, the reflection coefficient measured bybenchmarks/mpml_reflection.pyrises from 2.3e-5 (normal incidence) to 4.2e-4 (49 degrees) atp = 0, to 8.7e-5 to 2.6e-3 atp = 0.15, and to 1.1e-4 to 3.3e-3 atp = 0.20. Use the smallest value that stabilises your model; 0.1-0.2 is the usual range, and there is no universal value (it is medium-dependent). Must satisfy0 <= mpml_fraction < 1and requires at least two spatial dimensions. Optional, default 0.0. See the boundary-conditions documentation.surface_method –
How the free surface / topography implied by the vacuum cells (
buoyancy = mu = 0, see thebuoyancyargument) is discretised. One of:"ivm"(default): the improved vacuum method. The stress-free condition emerges from setting the vacuum cells’ parameters to zero; the interior update kernel is used everywhere unchanged. Simple and the historical behaviour, but its accuracy degrades as Poisson’s ratio increases."pm": the parameter-modified method of Cao and Chen (2018, Geophysics 83(6), T313-T332, https://doi.org/10.1190/geo2018-0098.1). This option is provisional (see Stability policy): the accuracy characteristics of the method are still being mapped, whilesurface_method="ivm"(the default) is stable. The value"pm"keeps working and keeps its meaning. In addition to the vacuum cells, the medium parameters at the solid cells lying on the discrete surface are modified once, before time stepping, so the stress-free condition is satisfied adaptively for any Poisson’s ratio: the per-component normal-stress stiffnesses are replaced by the surface-reduced values (a horizontal-surface, vertical-surface or corner/edge cell each keeping only the constitutive terms its traction-free condition allows), the surface-plane densities are halved, and (in 3D) the surface-plane shear moduli are halved. This gives markedly smaller surface-wave error than"ivm"at large Poisson’s ratio, at no per-step cost (the interior kernel is still used unchanged). Arbitrary staircase topography is supported through the vacuum region alone – there is no separate geometry argument. Recommended sampling is about 15 grid points per minimum (shear) wavelength near the surface. Requires at least one vacuum cell (raisesValueErrorotherwise, as there is no surface to modify), and rejects models containing fluid regions (mu == 0withlamb != 0, e.g. a water layer) withValueError, because the vacuum-based classifier cannot distinguish fluid from air. Supported in every dimensionality (1D, 2D and 3D) on the eager backend (backend="eager", no restrictions); in 1D the modification reduces to freezing the normal stress at the discrete surface cell (the exact stress-free condition), and no density or shear modification arises. The default compiled C/CUDA backend (backend="compiled") currently implements PM in 2D only (other dimensionalities raiseNotImplementedError), and additionally requires PML boundaries (boundary=...first-class boundary faces are not supported), andmpml_fraction=0– combinations violating these raiseNotImplementedError. Thetorch.compilePython mode (backend="torch_compile") always raisesNotImplementedErrorfor"pm". See the boundary-conditions documentation. Optional, default"ivm".
max_vel – The conservative speed bound used for the CFL condition and PML. If not specified, a bound is derived from the physical speeds and the density-weighted constitutive operator. Sharp density contrasts can require a larger bound than the pointwise P-wave and S-wave speeds. Optional, default None. Leaving this None makes the discretisation a property of the current model: the internal time step (and therefore RunInfo.step_ratio and the quadrature of the model gradient) changes as the model updates, so an inversion’s objective is not exactly comparable between iterations. Pass an explicit max_vel – a conservative bound over the whole inversion – for a reproducible objective. Nothing is read from the model when the call continues an earlier one: an omitted max_vel then takes the value recorded in initial_state. The value actually used is reported as RunInfo.max_vel. A value below the material/operator bound raises before propagation. Use deepwave.plan with automatic inference to inspect the bound. It has to be given when lamb, mu or buoyancy is batched by
torch.func.vmap(), which hides the values the maximum is otherwise read from. Every other torch.func transform (torch.func.grad(),torch.func.jacrev(),torch.func.jvp()) leaves them readable, so nothing has to be supplied under those. The maximum arrives as a Python number, so the absorbing boundary and the internal time step it chooses are constants of the call rather than differentiable functions of the model. When it is inferred, the model gradient at the cell the maximum is read from omits the term that acts through those two; every other cell’s gradient is unaffected. Passing max_vel removes that path. An exact model gradient of the fixed discrete call also requires internal-step sampling and lossless storage; see What Deepwave Calculates. Capability matrix lists, for each propagator, the models the maximum is read from.courant_number – Optional Courant number for the CFL time step. If None (default), the conservative
deepwave.DEFAULT_COURANT_NUMBERis used (historical behaviour, bit-identical). If given, it is the actual dimensionless Courant number targeted; it is validated against the critical Courant number for the chosen accuracy order (staggered-grid values) and errors if unstable. See the discretisation documentation. Optional, default None.survey_pad – Padding to apply around sources and receivers to restrict the simulation domain. See the documentation for the scalar propagator for a full description.
origin – The origin of the provided initial wavefields relative to the origin of the model. See
deepwave.scalar()for how this interacts with initial_state (the continuation rule): passing an origin that disagrees with the region initial_state records raises.nt –
The number of time steps to run the simulation for. Optional: if it is not given, the length of the source amplitudes is used. When both are given,
ntis the length of the run and the source amplitudes are zero-padded or truncated in time to it.The number of shots (the leading dimension of every per-shot tensor) is taken from the source locations if any are given, otherwise from the initial wavefields; with neither the call raises. See
deepwave.scalar().model_gradient_sampling_interval – The number of time steps between contributions to the model gradient. See
deepwave.scalar()for the full description; in particular, the CFLstep_ratiomultiplies it (the quadrature stride isstep_ratio * model_gradient_sampling_interval), it must dividentwhenever a model requires a gradient, and it applies only to the compiled backend – the pure-Python backends step every internal time step and return the exact discrete adjoint regardless of it.checkpoint_segments –
If given, split the time axis into this many segments and run each of them under
torch.utils.checkpoint, which is the memory lever for a run whose wavefield history does not fit: peak backward memory falls to roughly one segment’s history plus the states held at the segment boundaries, at the cost of running the forward pass of each segment a second time during the backward pass. None (the default) runs the whole time axis in one piece, exactly as before. It is the same thing as callingdeepwave.checkpointing.run_segments()withn_segments=andcheckpoint=True, and returns the same combined output – the same fields, the same info and the same auxiliary_state a direct call gives. initial_state, the storage arguments and every physics option are supported; nt may pad or truncate supplied source amplitudes for the whole run. Source-free nt calls, individual initial-wavefield arguments and per-step callbacks are not supported, and say so.Take the gradient with
loss.backward(). The checkpointing is reentrant, andtorch.utils.checkpointdoes not supporttorch.autograd.grad()(or aninputs=argument to.backward()) in that mode: it raises. If you needtorch.autograd.grad, calldeepwave.checkpointing.run_segments()directly withuse_reentrant=False.freq_taper_frac – The fraction of the end of the source and receiver amplitudes in the frequency domain to cosine taper if they are resampled due to the CFL condition.
time_pad_frac – The amount of zero padding that will be added to the source and receiver amplitudes before resampling and removed afterwards, if they are resampled due to the CFL condition, as a fraction of their length.
time_taper – Whether to apply a Hann window to resampled source and receiver amplitudes. Upsampling tapers its output after the inverse FFT; downsampling tapers its input before the FFT. The FFT-based resampling treats the time axis as periodic, so amplitudes that do not decay to (near) zero at the edges – e.g. field data cropped from a longer recording – can produce wraparound ringing. Tapering can reduce this ringing at the cost of attenuating genuine signal near the edges. Leave as False if amplitudes already taper to (near) zero at the edges.
check_output_finite – Whether to check, before returning, that the final wavefields and receiver amplitudes contain no
NaNorInf, raisingdeepwave.DeepwaveFloatingPointErrorif any do. Default True: a diverged run otherwise completes silently and only surfaces later, far from its cause. Each output is reduced on the device and the answer read back with a single synchronisation, so the cost is one pipeline drain per call – a fixed cost, whose relative size is therefore largest on the smallest calls. Measured over loops of 100 calls on two workstation GPUs: about +1.2% to +1.3% for a 100x100 grid with nt=300, +4% to +7% for a 40x40 grid with nt=60, and +0.5% to +1.9% for 300x300 with nt=1000 (see Troubleshooting). Pass False for a tight loop of very small calls, or where the outputs feed something that detects aNaNitself. The check is skipped undervmapand the othertorch.functransforms, which do not permit reading a value back from a batched tensor.forward_callback – A function that will be called during the forward pass. See
deepwave.CallbackStatefor the state that will be provided to the function. A callback can alter the running simulation, not only inspect it:deepwave.CallbackState.set_wavefield()writes into the simulation state, anddeepwave.CallbackState.get_gradient()returns a live view into the gradient accumulator whose in-place mutation is supported. Mutating whatdeepwave.CallbackState.get_wavefield()ordeepwave.CallbackState.get_model()returns is not: see that class’s docstring for the full contract.backward_callback – A function that will be called during the backward pass. See
deepwave.CallbackStatefor the state that will be provided to the function (the same mutation contract applies). Retrieving the reconstructed forward wavefield during a backward callback (get_wavefield(..., role="forward")) is a capability ofdeepwave.scalar()only; see itsbackward_callbackdocumentation. If the output being differentiated turns out to be unused, so that autograd has only an undefined (identically zero) gradient to propagate, the callback still fires on its usual schedule and is given an adjoint wavefield of zeros, neverNone.callback_frequency –
The number of user time steps between callback observations. Forward callbacks see steps
0, f, 2*f, ... < nt; backward callbacks see the same steps in reverse.CallbackState.stepandn_stepsuse user steps,dtis the user time step,internal_dtnames the CFL step, andtimeisstep * dtfrom this call’s start. The final state atntis returned normally, without an extra callback. Native execution chunks meet these boundaries independently of the model-gradient history stride, so requesting model gradients does not change the observation schedule.Each chunk carries a fixed cost that does not shrink with the chunk’s length: a separate entry into the backend for that chunk (on the compiled backend, its own set of kernel launches), the construction of a CallbackState, and the call to your callback. A backward pass split into more than one chunk also re-zeroes the per-shot model-gradient scratch buffers before every chunk after the first. Splitting a run more finely therefore pays those costs more times, so prefer the largest callback_frequency that still samples often enough for what you are doing, and keep small values for debugging and for animations that need every step.
backend – Which execution backend to use:
"auto"(the default),"compiled","eager"or"torch_compile". See Backends for what each value selects, what"auto"resolves to, and how the backends agree numerically."auto"resolves to the compiled C/CUDA kernel. Note thatsurface_method="pm"is implemented only on the compiled backend in 2-D and on the eager backend in any dimension; the other combinations raise rather than silently changing backend.python_backend – See
deepwave.scalar().storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated.
storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated.
storage_compression – Lossy: it changes the model gradient, by about 0.2-4% in 2-D and 0.2-8% in 3-D in relative L2 error. The name does not say so, which is why this entry does. If True, the sampled wavefield history kept for the model gradient is stored as 8-bit block max-abs quantisation (8 cells per spatial dimension per block, one full-precision scale per block). Measured relative L2 error against an uncompressed run: about 0.2-4% for 2-D problems and 0.2-8% for 3-D. For a matched geometry 3-D is consistently two to five times the 2-D error – a 3-D block shares one scale across 512 cells against 64 in 2-D – but the spread across geometries and loss functions is wide enough that the two ranges overlap. The error does not grow with the size of the problem: with the survey and the model anomaly held at fixed cell indices it is constant to five significant figures from 32x32 to 400x400 and from 32^3 to 120^3, and constant in nt once the record is long enough for the wavefield to reach the receivers. It does depend on the survey geometry and on the loss function – one fixed 3-D problem gives 3.4% under a sum of squared receiver amplitudes and 1.9% under a data residual – so treat these as ranges rather than a number to budget against. A barely illuminated gradient is the exception: a record too short for the wavefield to reach the receivers at all can give tens of percent, because there the gradient itself is nearly empty. The relative maximum error, defined as max|g_comp - g_exact| / max|g_exact|, is comparable to the relative L2 error rather than a fixed multiple of it – typically between 0.3 and 3 times it, and in 3-D more often below the L2 error than above. Do not use a per-cell relative error as a figure of merit: it is unbounded near the gradient’s zero crossings. The error is essentially independent of dtype (float32 and float64 agree to three or four significant figures) and exactly independent of storage_mode. The worst-affected values are the outermost cells of the model: a cell’s gradient there sums large, largely cancelling contributions from the absorbing layer, so the quantisation error does not cancel with them. Measured on the gradient of scalar_born’s dv, normalised by the gradient’s own maximum, the largest edge-cell error is 0.03-0.07 in 1-D, about 1e-4 in 2-D and about 1e-5 in 3-D, against below 1e-3, 2e-5 and 1e-5 respectively in the interior. Disabling compression removes quantisation error; it does not remove model-gradient sampling error. Exact discrete model derivatives also require an effective history stride of one and fixed setup parameters (see What Deepwave guarantees about gradients). Unaffected, bit for bit: the returned wavefields and auxiliary state, the receiver amplitudes, and the gradients with respect to the source amplitudes and the initial wavefields – compression touches only the stored history that forms the model gradient. Do not use it for `gradcheck`, adjoint or dot-product tests, or publication-quality gradients. In exchange it shrinks the offloaded host buffer by close to the size of the dtype in bytes – each cell becomes one byte, plus one full-precision scale per block – which is about 3.8x in 2-D and 4.0x in 3-D for float32, and about 7.1x and 7.9x for float64. That ratio is set by the dtype and the number of spatial dimensions, not by the size of the problem. Composed with storage_mode=”cpu” it runs roughly 2 to 3 times faster than uncompressed offload, because it reduces the PCIe traffic that offload is bottlenecked on. Defaults to False.
location_interpolation –
A string controlling how non-integer (float) source/receiver coordinates are handled. One of:
”auto” (default): float coordinates that do not lie on the grid node of the field component being placed are interpolated onto the grid using the method of Hicks (Kaiser-windowed sinc); float coordinates that do lie on a node (within a small tolerance), and integer (torch.long) coordinates, take the exact path and are bit-for-bit identical to providing integer cell indices.
”hicks”: always use Hicks interpolation.
”none”: never interpolate; only the exact path is accepted (integer (torch.long) coordinates, or float coordinates that lie on a node within a small tolerance). An off-node float coordinate raises a
ValueErrorrather than being silently truncated to the node below it, asv0.0.27did.
Coordinates are in grid cells relative to the model origin. Because this is a staggered-grid propagator, each velocity component lives half a cell from the normal-stress (pressure) node in its own dimension, so integer index
Nand floatN + 0.5denote the same physical point for that component (avxsource at integer3equals float3.5); the pressure component is on the regular grid. With genuinely off-grid coordinates the propagator performs band-limited injection/recording, an approximation. Adeepwave.Hicksobject may be passed as any location argument for full control (dipoles, a custom component offset, or free surfaces); the propagator uses its offset as given and does not check it against the component. Defaults to “auto”."auto"interpolates a floating-point locations Tensor only when at least one non-ignored coordinate lies more thandeepwave.ON_NODE_TOLERANCEcells off its component’s grid node – except that a floating-point Tensor withrequires_grad=Trueis always interpolated, even when every coordinate is on-node, because only the interpolated path carries gradients back to the positions. That changes the forward values for an on-noderequires_gradlocations Tensor relative to the same Tensor withoutrequires_grad. Passlocation_interpolation="none"for the exact path (positions are then not differentiable), or accept the band-limited values.RunInfo.location_interpolation_usedrecords which path was taken:"none"or"hicks", or"mixed"if this propagator has several channels of one kind (several source components, say) and they did not all take the same path.location_interpolation_halfwidth – The halfwidth of the Hicks interpolation window (see
deepwave.Hicks) used when float coordinates are interpolated. Defaults to 4.
Elastic Function¶
- deepwave.elastic(lamb: Tensor, mu: Tensor, buoyancy: Tensor, grid_spacing: float | Sequence[float], dt: float, *, sources: Mapping[str, tuple[Tensor, Tensor | Hicks] | tuple[Tensor, Tensor | Hicks, Tensor | None]] | None = None, receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, source_amplitudes_pressure_rate: Tensor | None = None, source_amplitudes_p: Tensor | None = None, source_amplitudes_z: Tensor | None = None, source_amplitudes_y: Tensor | None = None, source_amplitudes_x: Tensor | None = None, source_locations_pressure_rate: Tensor | Hicks | None = None, source_locations_p: Tensor | Hicks | None = None, source_locations_z: Tensor | Hicks | None = None, source_locations_y: Tensor | Hicks | None = None, source_locations_x: Tensor | Hicks | None = None, source_mask_pressure_rate: Tensor | None = None, source_mask_z: Tensor | None = None, source_mask_y: Tensor | None = None, source_mask_x: Tensor | None = None, receiver_locations_p: Tensor | Hicks | None = None, receiver_locations_z: Tensor | Hicks | None = None, receiver_locations_y: Tensor | Hicks | None = None, receiver_locations_x: Tensor | Hicks | None = None, receiver_mask_p: Tensor | None = None, receiver_mask_z: Tensor | None = None, receiver_mask_y: Tensor | None = None, receiver_mask_x: Tensor | None = None, vz_0: Tensor | None = None, vy_0: Tensor | None = None, vx_0: Tensor | None = None, sigmazz_0: Tensor | None = None, sigmayz_0: Tensor | None = None, sigmaxz_0: Tensor | None = None, sigmayy_0: Tensor | None = None, sigmaxy_0: Tensor | None = None, sigmaxx_0: Tensor | None = None, initial_state: PropagatorOutput | Mapping[str, Tensor | AuxiliaryState] | None = None, accuracy: Literal[2, 4, 6, 8] = 4, pml_width: int | Sequence[int] = 20, boundary: str | Sequence[str] | None = None, pml_freq: float | None = None, mpml_fraction: float = 0.0, surface_method: Literal['ivm', 'pm'] = 'ivm', max_vel: float | None = None, courant_number: float | None = None, survey_pad: int | Sequence[int | None] | None = None, origin: Sequence[int] | None = None, nt: int | None = None, model_gradient_sampling_interval: int = 1, checkpoint_segments: int | None = None, freq_taper_frac: float = 0.0, time_pad_frac: float = 0.0, time_taper: bool = False, check_output_finite: bool = True, forward_callback: Callback | None = None, backward_callback: Callback | None = None, callback_frequency: int = 1, backend: str = 'auto', python_backend: Literal['eager', 'jit', 'compile'] | bool | None = None, storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None, location_interpolation: Literal['auto', 'hicks', 'none'] = 'auto', location_interpolation_halfwidth: int = 4) PropagatorOutput¶
Elastic wave propagation (functional interface).
Stability: stable (see Stability policy).
This function performs forward modelling with the elastic wave equation. The outputs are differentiable with respect to the input float torch.Tensors.
For computational performance, multiple shots may be propagated simultaneously.
This propagator uses a staggered grid. See the documentation for a description of the grid layout.
Deepwave orders spatial dimensions from slowest-varying to fastest-varying and attaches no physical meaning to any of them; the component suffixes count from the fastest axis, so a 2-D run uses
_yand_xand a 3-D run uses_z,_yand_x. See Dimension order and the axis convention.- Parameters:
lamb – The first Lamé parameter model, lambda, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.mu – The second Lamé parameter model, mu, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.buoyancy – The buoyancy (1/density) model. A cell with
buoyancy = 0is a vacuum, not an infinitely dense cell: it is a sentinel, not a literal reciprocal density, so do not compute1/densityfor vacuum cells (build the parameters fromvp = vs = rho = 0viadeepwave.vpvsrho_to_lambmubuoyancy(), which mapsrho = 0tobuoyancy = 0). A vacuum cell has zero density and, withlamb = mu = 0, zero stiffness, which is how a free surface is created (the “improved vacuum” method: set the vacuum cells’lamb,muandbuoyancyto zero and usepml_width = 0on that face). See the vacuum sentinel in Boundary conditions, which also explains how the sentinel is averaged onto the staggered nodes. It is of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.grid_spacing – The spatial grid cell size. It can be a single number that will be used for all dimensions, or a number for each dimension.
dt – The time step interval of the input and output (internally a smaller interval may be used in propagation to obey the CFL (Courant-Friedrichs-Lewy) condition for stability). Due to the staggered time grid, stress-related fields (including pressure) are at integer time steps t*dt, while velocity-related fields are at half time steps (t-0.5)*dt. Deepwave is unit-agnostic: choose any single consistent system of units for
lamb,mu,buoyancy,grid_spacing, anddt; see Units and source conventions.sources – This simulation’s sources, keyed by channel. This is the canonical way to specify a survey. Each value is
(amplitudes, locations), or(amplitudes, locations, mask)to include an activity mask. The channels arepressure_rate,z,y,x(zonly in 3-D,yonly in 2-D and 3-D);pis a deprecated spelling ofpressure_ratehere. Exactly equivalent to the flatsource_amplitudes_*/source_locations_*keywords, which remain permanently supported; giving one channel in both forms raises. Optional.receivers – This simulation’s receivers, keyed by channel, as the canonical alternative to the flat
receiver_locations*keywords. Each value is a locations object, or(locations, mask)to include an activity mask. The channels arep,z,y,x(zonly in 3-D,yonly in 2-D and 3-D). Giving one channel in both forms raises. Optional.source_amplitudes_pressure_rate – A Tensor with dimensions [shot, source, time] of pressure rates, with units of pressure/time (a positive amplitude is compressional). This differs from the acoustic family, whose
source_amplitudes_volume_rateis a volume-injection rate; see Units and source conventions for the conversion. Each sample is added to the update from p(t*dt) to p((t+1)*dt), so it acts at (t+0.5)*dt, half a step after the pressure receiver of the same index is recorded. To drive the propagation with a volumetric (extended) source instead of hand-placed point sources, build the amplitudes and integer locations withdeepwave.wavefields.source_field_to_sources().source_amplitudes_p – Deprecated spelling of
source_amplitudes_pressure_rate, which means exactly the same thing. It warnsdeepwave.DeepwaveFutureWarningand will be removed in Deepwave 0.4.0: the letterpnames a pressure rate here and a volume rate on the acoustic family, two quantities that differ by roughly the bulk modulus, so a source channel says which one it injects; see Units and source conventions.premains the receiver channel’s name. Passing both raises. Optional.source_amplitudes_z – A Tensor with dimensions [shot, source, time] of force densities in the z direction, with units of force/volume in both 2-D and 3-D. Each sample is added to the update from vz((t-0.5)*dt) to vz((t+0.5)*dt), so it acts at t*dt, half a step after the velocity receiver of the same index is recorded. This channel exists only in 3-D.
source_amplitudes_y – A Tensor with dimensions [shot, source, time] of force densities in the y direction, with units of force/volume. Timed as
source_amplitudes_z.source_amplitudes_x – A Tensor with dimensions [shot, source, time] of force densities in the x direction, with units of force/volume. Timed as
source_amplitudes_z.source_locations_pressure_rate – A Tensor containing the locations of pressure sources. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_p – Deprecated spelling of
source_locations_pressure_rate, assource_amplitudes_pis ofsource_amplitudes_pressure_rate. Passing both raises. Optional.source_locations_z – A Tensor with dimensions [shot, source, ndim], containing the index in the ndim spatial dimensions of the cell that each source oriented in the z spatial dimension is located in, relative to the origin of the model. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_y – A Tensor containing the locations of sources oriented in the y spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_x – A Tensor containing the locations of sources oriented in the x spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_mask_pressure_rate – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
pressure_ratechannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_pressure_rateare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_pressure_rate, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_z – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_y – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
ychannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_x – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
xchannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_locations_p – A Tensor containing the coordinates of the pressure receivers. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_z – A Tensor with dimensions [shot, receiver, ndim], containing the coordinates of the cell containing each receiver oriented in the z spatial dimension. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_y – A Tensor containing the coordinates of the receivers oriented in the y spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_x – A Tensor containing the coordinates of the receivers oriented in the x spatial dimension. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.vz_0 – Initial vz (velocity in the z dimension) wavefield at time step -1/2. Like every initial wavefield, it may be provided either at the shape of the simulation domain (the extracted model region plus the PML), which is the shape a previous call returns, or at the shape of the extracted model region itself, which Deepwave zero-pads for you; see the wavefield_0 entry of
deepwave.scalar()for the full description.vy_0 – Initial vy (velocity in the y dimension) wavefield at time step -1/2.
vx_0 – Initial vx (velocity in the x dimension) wavefield at time step -1/2.
sigmazz_0 – Initial value for the zz component of the stress field at time step 0.
sigmayz_0 – Initial value for the yz component of the stress field at time step 0.
sigmaxz_0 – Initial value for the xz component of the stress field at time step 0.
sigmayy_0 – Initial value for the yy component of the stress field at time step 0.
sigmaxy_0 – Initial value for the xy component of the stress field at time step 0.
sigmaxx_0 – Initial value for the xx component of the stress field at time step 0.
initial_state –
An optional bundle of initial wavefields, supplied as either a
deepwave.PropagatorOutput(the return of a previous call), that output’s final_state mapping, or any mapping whose keys are the public state field names (vz_0, sigmazz_0, …) and auxiliary_state (adeepwave.AuxiliaryStatefrom a previous call). Each entry fills the correspondingly-named initial wavefield that was not also passed explicitly (matching is by name, so the public-vs-backend wavefield ordering is irrelevant), so a previous output can be passed back in to continue the simulation (its receiver_amplitudes_* fields are ignored), and it is the unambiguous route: the auxiliary state records the propagator, accuracy, PML width, boundary conditions, number of relaxation mechanisms, simulation-domain shape and internal time step it was produced with, so a continuation that does not match them raises rather than producing quiet nonsense, and one whose pml_freq or max_vel differs – which reshapes the absorbing boundary without changing what the tensors are – warns. The survey origin is recorded and reused: see the continuation rule below.Continuation rule. When initial_state carries a region – a PropagatorOutput from a previous call, whose RunInfo.origin and RunInfo.extent record the region that run used, or a AuxiliaryState carrying the same – and you pass neither survey_pad nor origin, that stored region is reused: the continuation propagates exactly the same part of the model, and the new call’s sources and receivers must lie inside it (they are checked; a location outside it raises). If you pass survey_pad or origin explicitly, your value wins and the stored wavefields must match the region it implies; a disagreement raises rather than silently re-windowing the simulation. Passing the previous call’s output (initial_state=out) is the unambiguous route. A mapping of bare tensors records no region at all, so it warns and assumes origin zero unless you pass origin.
The individual absorbing-boundary field names (m_vzz_0, …, m_sigmaxxx_0) are still accepted as keys, with a FutureWarning; they will stop being accepted in Deepwave 0.4.0. Providing a wavefield both here and as an explicit argument raises an error. For the continuation to exactly reproduce a single run over the combined time range, the same internal time step and the same absorbing boundary must be used throughout. The first holds when the user dt already satisfies the CFL condition (no internal sub-stepping); otherwise the segment boundary introduces a small discretisation difference. The second is automatic: when pml_freq or max_vel is omitted, the value recorded in initial_state is used, rather than one inferred from this call’s own portion of the source record or from its model, so the continuation builds the same absorbing boundary as the run it continues. Passing either explicitly overrides that, and a mismatch with the recorded value then warns; a mismatched internal time step raises. When a gradient will be taken, each call retains the initial wavefields it is given until its backward pass runs – the second-order (Hessian-vector-product) path replays the propagation from them – so a differentiable continuation loop holds one full wavefield set per iteration, and dropping your own reference to the previous output does not release it; run segments that do not need a gradient under
torch.no_grad(), or wrap segments intorch.utils.checkpoint.checkpointoverdeepwave.checkpointing.run_segments(), to bound the peak memory. If initial_state is a PropagatorOutput and neither origin nor survey_pad is also passed, the survey origin used to produce it is recovered automatically, so the continuation extracts the same region of the model rather than assuming an origin of zero.The number of shots (the leading dimension of every per-shot tensor) is taken from the source locations if any are given, otherwise from the initial wavefields. So a call with nt and no sources takes its shot count from the wavefields given here; with neither sources nor initial wavefields the call raises. Optional, default None.
accuracy – The finite difference order of accuracy. Possible values are 2, 4, 6, and 8, with larger numbers resulting in more accurate results but greater computational cost. Default 4.
pml_width –
A single number, or a sequence of numbers for each side, specifying the width (in number of cells) of the PML that prevents reflections from the edges of the model. If a single value is provided, it will be used for all edges. If a sequence is provided, it should contain values for the edges in the following order:
beginning of first dimension
end of first dimension
beginning of second dimension
end of second dimension
…
Larger values result in smaller reflections, with values of 10 to 20 being typical. For a reflective rigid surface, set the value for that edge to be zero. The wavespeed in the PML region is obtained by replicating the values on the edge of the model. Optional, default 20. A face whose
pml_widthis zero does not absorb: it becomes an implicit reflecting boundary whose type depends on the propagator and the field component. See Reflecting edges for the per-propagator reflection coefficient and surface location, and prefer naming the condition withboundary(ordeepwave.boundaries()), which also uses the exact image rather than this approximate one.boundary – An optional single string, applying to every face, or a list of 2 * ndim strings selecting a first-class flat-face boundary condition per face, in the same order as pml_width and with the same semantics as
deepwave.acoustic()’s boundary (“pml”, “free”, “rigid”, or “periodic”; a non-“pml” face requires pml_width == 0 on that face). This is a fast, flat-face image-method shortcut for the common case of a boundary lying exactly on a domain edge – it does not replace the improved vacuum method (IVM, see the buoyancy argument above), which remains the only way to represent an irregular or topographic free surface. The per-field parities (which of the stress-tensor and velocity components are imaged odd/even, and which need no imaging at all) are derived from Robertsson (1996)’s stress-image method and documented, with citations, in docs/boundaries.rst’s Policy section. Validated on both the eager (backend=”eager”) and the default compiled C/CUDA backends, against analytic reflection coefficients, against the improved vacuum method, and by gradient checking. Forward-mode AD (torch.func.jvp) and the compiled second-order (HVP) path – which route through elastic_born’s compiled backend – also support a non-“pml” face (elastic_born has its own bc-threaded compiled kernel). Availability: “pml” is accepted on every face at every accuracy, and “rigid” on the beginning of a dimension at every accuracy and on the end of a dimension at accuracy=2. “rigid” on the end of a dimension with accuracy >= 4, and “free” and “periodic” on any face, raisedeepwave.DeepwaveNotImplementedError: those guard-ring fills do not conserve a discrete energy, so the solution can grow without bound. Model a free surface with a vacuum layer (the improved vacuum method) instead; put a “rigid” face at the beginning of the dimension (flip the model along that axis), or use accuracy=2. Faces may be accepted in a later release; none is removed.pml_freq –
The frequency to use when constructing the PML, usually the dominant frequency of the source wavelet: the PML absorbs best near this frequency, and choosing it poorly makes the edges more reflective. Optional. If not specified, it is inferred from the peak of the source amplitudes’ spectrum (which returns the wavelet’s own centre frequency for a Ricker), or, if the simulation has no sources at all, from
0.5 / dt / 5, a fifth of the Nyquist frequency. Nothing is inferred when the call continues an earlier one: an omittedpml_freqthen takes the value recorded ininitial_state. The value actually used is reported asout.info.pml_freq. Pin it explicitly for any published result: leaving it inferred makes the absorbing boundary depend on the wavelet, so changing the wavelet also changes the boundary. The source-amplitude gradient does not follow that path, so pinpml_freqwhen you differentiate with respect to the source. See Choosing pml_freq.Note
Deepwave 0.0.27 and earlier used a fixed 25 Hz here. A seismic call with a 25 Hz wavelet therefore infers exactly 25.0 and gets the same numbers as before; a call whose inferred value is anything else warns once, naming
pml_freq=25.0as the line that restores the old behaviour. That warning is a migration aid and is removed in 0.4.0.mpml_fraction – The multiaxial PML (M-PML) cross-damping fraction, an opt-in stability option for elastic media. Inside each absorbing layer the standard PML damps only the direction normal to that layer’s face; with
mpml_fraction = pthe damping profile of that layer is also applied, scaled byp, to each of the other axes, so every axis in the layer is damped byptimes that layer’s own profile in addition to whatever its own layer contributes. This is the multiaxial PML of Meza-Fajardo and Papageorgiou (2008, https://doi.org/10.1785/0120070223), in which the same fraction is calledp. The default of 0 gives the standard CFS-C-PML, with behaviour and performance byte-identical to not having the feature. Elastic simulations that combine a thin region between two facing free surfaces with a high Poisson’s ratio and a perpendicular PML can suffer a slow exponential (late-time) instability, which a small positive value cures. The trade-off is that the M-PML is no longer perfectly matched, so the layer reflects more: on a homogeneous elastic half-space withpml_width=20, the reflection coefficient measured bybenchmarks/mpml_reflection.pyrises from 2.3e-5 (normal incidence) to 4.2e-4 (49 degrees) atp = 0, to 8.7e-5 to 2.6e-3 atp = 0.15, and to 1.1e-4 to 3.3e-3 atp = 0.20. Use the smallest value that stabilises your model; 0.1-0.2 is the usual range, and there is no universal value (it is medium-dependent). Must satisfy0 <= mpml_fraction < 1and requires at least two spatial dimensions. Optional, default 0.0. See the boundary-conditions documentation.surface_method –
How the free surface / topography implied by the vacuum cells (
buoyancy = mu = 0, see thebuoyancyargument) is discretised. One of:"ivm"(default): the improved vacuum method. The stress-free condition emerges from setting the vacuum cells’ parameters to zero; the interior update kernel is used everywhere unchanged. Simple and the historical behaviour, but its accuracy degrades as Poisson’s ratio increases."pm": the parameter-modified method of Cao and Chen (2018, Geophysics 83(6), T313-T332, https://doi.org/10.1190/geo2018-0098.1). This option is provisional (see Stability policy): the accuracy characteristics of the method are still being mapped, whilesurface_method="ivm"(the default) is stable. The value"pm"keeps working and keeps its meaning. In addition to the vacuum cells, the medium parameters at the solid cells lying on the discrete surface are modified once, before time stepping, so the stress-free condition is satisfied adaptively for any Poisson’s ratio: the per-component normal-stress stiffnesses are replaced by the surface-reduced values (a horizontal-surface, vertical-surface or corner/edge cell each keeping only the constitutive terms its traction-free condition allows), the surface-plane densities are halved, and (in 3D) the surface-plane shear moduli are halved. This gives markedly smaller surface-wave error than"ivm"at large Poisson’s ratio, at no per-step cost (the interior kernel is still used unchanged). Arbitrary staircase topography is supported through the vacuum region alone – there is no separate geometry argument. Recommended sampling is about 15 grid points per minimum (shear) wavelength near the surface. Requires at least one vacuum cell (raisesValueErrorotherwise, as there is no surface to modify), and rejects models containing fluid regions (mu == 0withlamb != 0, e.g. a water layer) withValueError, because the vacuum-based classifier cannot distinguish fluid from air. Supported in every dimensionality (1D, 2D and 3D) on the eager backend (backend="eager", no restrictions); in 1D the modification reduces to freezing the normal stress at the discrete surface cell (the exact stress-free condition), and no density or shear modification arises. The default compiled C/CUDA backend (backend="compiled") currently implements PM in 2D only (other dimensionalities raiseNotImplementedError), and additionally requires PML boundaries (boundary=...first-class boundary faces are not supported), andmpml_fraction=0– combinations violating these raiseNotImplementedError. Thetorch.compilePython mode (backend="torch_compile") always raisesNotImplementedErrorfor"pm". See the boundary-conditions documentation. Optional, default"ivm".
max_vel – The conservative speed bound used for the CFL condition and PML. If not specified, a bound is derived from the physical speeds and the density-weighted constitutive operator. Sharp density contrasts can require a larger bound than the pointwise P-wave and S-wave speeds. Optional, default None. Leaving this None makes the discretisation a property of the current model: the internal time step (and therefore RunInfo.step_ratio and the quadrature of the model gradient) changes as the model updates, so an inversion’s objective is not exactly comparable between iterations. Pass an explicit max_vel – a conservative bound over the whole inversion – for a reproducible objective. Nothing is read from the model when the call continues an earlier one: an omitted max_vel then takes the value recorded in initial_state. The value actually used is reported as RunInfo.max_vel. A value below the material/operator bound raises before propagation. Use deepwave.plan with automatic inference to inspect the bound. It has to be given when lamb, mu or buoyancy is batched by
torch.func.vmap(), which hides the values the maximum is otherwise read from. Every other torch.func transform (torch.func.grad(),torch.func.jacrev(),torch.func.jvp()) leaves them readable, so nothing has to be supplied under those. The maximum arrives as a Python number, so the absorbing boundary and the internal time step it chooses are constants of the call rather than differentiable functions of the model. When it is inferred, the model gradient at the cell the maximum is read from omits the term that acts through those two; every other cell’s gradient is unaffected. Passing max_vel removes that path. An exact model gradient of the fixed discrete call also requires internal-step sampling and lossless storage; see What Deepwave Calculates. Capability matrix lists, for each propagator, the models the maximum is read from.courant_number – Optional Courant number for the CFL time step. If None (default), the conservative
deepwave.DEFAULT_COURANT_NUMBERis used (historical behaviour, bit-identical). If given, it is the actual dimensionless Courant number targeted; it is validated against the critical Courant number for the chosen accuracy order (staggered-grid values) and errors if unstable. See the discretisation documentation. Optional, default None.survey_pad – Padding to apply around sources and receivers to restrict the simulation domain. See the documentation for the scalar propagator for a full description.
origin – The origin of the provided initial wavefields relative to the origin of the model. See
deepwave.scalar()for how this interacts with initial_state (the continuation rule): passing an origin that disagrees with the region initial_state records raises.nt –
The number of time steps to run the simulation for. Optional: if it is not given, the length of the source amplitudes is used. When both are given,
ntis the length of the run and the source amplitudes are zero-padded or truncated in time to it.The number of shots (the leading dimension of every per-shot tensor) is taken from the source locations if any are given, otherwise from the initial wavefields; with neither the call raises. See
deepwave.scalar().model_gradient_sampling_interval – The number of time steps between contributions to the model gradient. See
deepwave.scalar()for the full description; in particular, the CFLstep_ratiomultiplies it (the quadrature stride isstep_ratio * model_gradient_sampling_interval), it must dividentwhenever a model requires a gradient, and it applies only to the compiled backend – the pure-Python backends step every internal time step and return the exact discrete adjoint regardless of it.checkpoint_segments –
If given, split the time axis into this many segments and run each of them under
torch.utils.checkpoint, which is the memory lever for a run whose wavefield history does not fit: peak backward memory falls to roughly one segment’s history plus the states held at the segment boundaries, at the cost of running the forward pass of each segment a second time during the backward pass. None (the default) runs the whole time axis in one piece, exactly as before. It is the same thing as callingdeepwave.checkpointing.run_segments()withn_segments=andcheckpoint=True, and returns the same combined output – the same fields, the same info and the same auxiliary_state a direct call gives. initial_state, the storage arguments and every physics option are supported; nt may pad or truncate supplied source amplitudes for the whole run. Source-free nt calls, individual initial-wavefield arguments and per-step callbacks are not supported, and say so.Take the gradient with
loss.backward(). The checkpointing is reentrant, andtorch.utils.checkpointdoes not supporttorch.autograd.grad()(or aninputs=argument to.backward()) in that mode: it raises. If you needtorch.autograd.grad, calldeepwave.checkpointing.run_segments()directly withuse_reentrant=False.freq_taper_frac – The fraction of the end of the source and receiver amplitudes in the frequency domain to cosine taper if they are resampled due to the CFL condition.
time_pad_frac – The amount of zero padding that will be added to the source and receiver amplitudes before resampling and removed afterwards, if they are resampled due to the CFL condition, as a fraction of their length.
time_taper – Whether to apply a Hann window to resampled source and receiver amplitudes. Upsampling tapers its output after the inverse FFT; downsampling tapers its input before the FFT. The FFT-based resampling treats the time axis as periodic, so amplitudes that do not decay to (near) zero at the edges – e.g. field data cropped from a longer recording – can produce wraparound ringing. Tapering can reduce this ringing at the cost of attenuating genuine signal near the edges. Leave as False if amplitudes already taper to (near) zero at the edges.
check_output_finite – Whether to check, before returning, that the final wavefields and receiver amplitudes contain no
NaNorInf, raisingdeepwave.DeepwaveFloatingPointErrorif any do. Default True: a diverged run otherwise completes silently and only surfaces later, far from its cause. Each output is reduced on the device and the answer read back with a single synchronisation, so the cost is one pipeline drain per call – a fixed cost, whose relative size is therefore largest on the smallest calls. Measured over loops of 100 calls on two workstation GPUs: about +1.2% to +1.3% for a 100x100 grid with nt=300, +4% to +7% for a 40x40 grid with nt=60, and +0.5% to +1.9% for 300x300 with nt=1000 (see Troubleshooting). Pass False for a tight loop of very small calls, or where the outputs feed something that detects aNaNitself. The check is skipped undervmapand the othertorch.functransforms, which do not permit reading a value back from a batched tensor.forward_callback – A function that will be called during the forward pass. See
deepwave.CallbackStatefor the state that will be provided to the function. A callback can alter the running simulation, not only inspect it:deepwave.CallbackState.set_wavefield()writes into the simulation state, anddeepwave.CallbackState.get_gradient()returns a live view into the gradient accumulator whose in-place mutation is supported. Mutating whatdeepwave.CallbackState.get_wavefield()ordeepwave.CallbackState.get_model()returns is not: see that class’s docstring for the full contract.backward_callback – A function that will be called during the backward pass. See
deepwave.CallbackStatefor the state that will be provided to the function (the same mutation contract applies). Retrieving the reconstructed forward wavefield during a backward callback (get_wavefield(..., role="forward")) is a capability ofdeepwave.scalar()only; see itsbackward_callbackdocumentation. If the output being differentiated turns out to be unused, so that autograd has only an undefined (identically zero) gradient to propagate, the callback still fires on its usual schedule and is given an adjoint wavefield of zeros, neverNone.callback_frequency –
The number of user time steps between callback observations. Forward callbacks see steps
0, f, 2*f, ... < nt; backward callbacks see the same steps in reverse.CallbackState.stepandn_stepsuse user steps,dtis the user time step,internal_dtnames the CFL step, andtimeisstep * dtfrom this call’s start. The final state atntis returned normally, without an extra callback. Native execution chunks meet these boundaries independently of the model-gradient history stride, so requesting model gradients does not change the observation schedule.Each chunk carries a fixed cost that does not shrink with the chunk’s length: a separate entry into the backend for that chunk (on the compiled backend, its own set of kernel launches), the construction of a CallbackState, and the call to your callback. A backward pass split into more than one chunk also re-zeroes the per-shot model-gradient scratch buffers before every chunk after the first. Splitting a run more finely therefore pays those costs more times, so prefer the largest callback_frequency that still samples often enough for what you are doing, and keep small values for debugging and for animations that need every step.
backend – Which execution backend to use:
"auto"(the default),"compiled","eager"or"torch_compile". See Backends for what each value selects, what"auto"resolves to, and how the backends agree numerically."auto"resolves to the compiled C/CUDA kernel. Note thatsurface_method="pm"is implemented only on the compiled backend in 2-D and on the eager backend in any dimension; the other combinations raise rather than silently changing backend.python_backend – See
deepwave.scalar().storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated.
storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated.
storage_compression – Lossy: it changes the model gradient, by about 0.2-4% in 2-D and 0.2-8% in 3-D in relative L2 error. The name does not say so, which is why this entry does. If True, the sampled wavefield history kept for the model gradient is stored as 8-bit block max-abs quantisation (8 cells per spatial dimension per block, one full-precision scale per block). Measured relative L2 error against an uncompressed run: about 0.2-4% for 2-D problems and 0.2-8% for 3-D. For a matched geometry 3-D is consistently two to five times the 2-D error – a 3-D block shares one scale across 512 cells against 64 in 2-D – but the spread across geometries and loss functions is wide enough that the two ranges overlap. The error does not grow with the size of the problem: with the survey and the model anomaly held at fixed cell indices it is constant to five significant figures from 32x32 to 400x400 and from 32^3 to 120^3, and constant in nt once the record is long enough for the wavefield to reach the receivers. It does depend on the survey geometry and on the loss function – one fixed 3-D problem gives 3.4% under a sum of squared receiver amplitudes and 1.9% under a data residual – so treat these as ranges rather than a number to budget against. A barely illuminated gradient is the exception: a record too short for the wavefield to reach the receivers at all can give tens of percent, because there the gradient itself is nearly empty. The relative maximum error, defined as max|g_comp - g_exact| / max|g_exact|, is comparable to the relative L2 error rather than a fixed multiple of it – typically between 0.3 and 3 times it, and in 3-D more often below the L2 error than above. Do not use a per-cell relative error as a figure of merit: it is unbounded near the gradient’s zero crossings. The error is essentially independent of dtype (float32 and float64 agree to three or four significant figures) and exactly independent of storage_mode. The worst-affected values are the outermost cells of the model: a cell’s gradient there sums large, largely cancelling contributions from the absorbing layer, so the quantisation error does not cancel with them. Measured on the gradient of scalar_born’s dv, normalised by the gradient’s own maximum, the largest edge-cell error is 0.03-0.07 in 1-D, about 1e-4 in 2-D and about 1e-5 in 3-D, against below 1e-3, 2e-5 and 1e-5 respectively in the interior. Disabling compression removes quantisation error; it does not remove model-gradient sampling error. Exact discrete model derivatives also require an effective history stride of one and fixed setup parameters (see What Deepwave guarantees about gradients). Unaffected, bit for bit: the returned wavefields and auxiliary state, the receiver amplitudes, and the gradients with respect to the source amplitudes and the initial wavefields – compression touches only the stored history that forms the model gradient. Do not use it for `gradcheck`, adjoint or dot-product tests, or publication-quality gradients. In exchange it shrinks the offloaded host buffer by close to the size of the dtype in bytes – each cell becomes one byte, plus one full-precision scale per block – which is about 3.8x in 2-D and 4.0x in 3-D for float32, and about 7.1x and 7.9x for float64. That ratio is set by the dtype and the number of spatial dimensions, not by the size of the problem. Composed with storage_mode=”cpu” it runs roughly 2 to 3 times faster than uncompressed offload, because it reduces the PCIe traffic that offload is bottlenecked on. Defaults to False.
location_interpolation –
A string controlling how non-integer (float) source/receiver coordinates are handled. One of:
”auto” (default): float coordinates that do not lie on the grid node of the field component being placed are interpolated onto the grid using the method of Hicks (Kaiser-windowed sinc); float coordinates that do lie on a node (within a small tolerance), and integer (torch.long) coordinates, take the exact path and are bit-for-bit identical to providing integer cell indices.
”hicks”: always use Hicks interpolation.
”none”: never interpolate; only the exact path is accepted (integer (torch.long) coordinates, or float coordinates that lie on a node within a small tolerance). An off-node float coordinate raises a
ValueErrorrather than being silently truncated to the node below it, asv0.0.27did.
Coordinates are in grid cells relative to the model origin. Because this is a staggered-grid propagator, each velocity component lives half a cell from the normal-stress (pressure) node in its own dimension, so integer index
Nand floatN + 0.5denote the same physical point for that component (avxsource at integer3equals float3.5); the pressure component is on the regular grid. With genuinely off-grid coordinates the propagator performs band-limited injection/recording, an approximation. Adeepwave.Hicksobject may be passed as any location argument for full control (dipoles, a custom component offset, or free surfaces); the propagator uses its offset as given and does not check it against the component. Defaults to “auto”."auto"interpolates a floating-point locations Tensor only when at least one non-ignored coordinate lies more thandeepwave.ON_NODE_TOLERANCEcells off its component’s grid node – except that a floating-point Tensor withrequires_grad=Trueis always interpolated, even when every coordinate is on-node, because only the interpolated path carries gradients back to the positions. That changes the forward values for an on-noderequires_gradlocations Tensor relative to the same Tensor withoutrequires_grad. Passlocation_interpolation="none"for the exact path (positions are then not differentiable), or accept the band-limited values.RunInfo.location_interpolation_usedrecords which path was taken:"none"or"hicks", or"mixed"if this propagator has several channels of one kind (several source components, say) and they did not all take the same path.location_interpolation_halfwidth – The halfwidth of the Hicks interpolation window (see
deepwave.Hicks) used when float coordinates are interpolated. Defaults to 4.
- Returns:
a tuple subclass whose fields, in order, are:
vz_0: Final velocity wavefield in the z-dimension (if ndim == 3).
vy_0: Final velocity wavefield in the y-dimension (if ndim >= 2).
vx_0: Final velocity wavefield in the x-dimension.
sigmazz_0: Final stress wavefield (zz component) (if ndim == 3).
sigmayz_0: Final stress wavefield (yz component) (if ndim == 3).
sigmaxz_0: Final stress wavefield (xz component) (if ndim == 3).
sigmayy_0: Final stress wavefield (yy component) (if ndim >= 2).
sigmaxy_0: Final stress wavefield (xy component) (if ndim >= 2).
sigmaxx_0: Final stress wavefield (xx component).
auxiliary_state: A
deepwave.AuxiliaryStateholding the absorbing boundary’s memory variables. Opaque: pass it back (as part of initial_state) to continue the simulation; its contents are implementation state rather than physics.receiver_amplitudes_p: Recorded pressure data, with units of pressure. The samples correspond to times t*dt. This “pressure” is minus the mean of the recorded normal stresses,
-(sigma_xx + ... )/ndim. In 3D that is the usual pressure-(sigma_xx+sigma_yy+sigma_zz)/3, but in 2D it is the in-plane mean normal stress-(sigma_xx+sigma_yy)/2, which under plane strain differs from the true thermodynamic pressure (the out-of-plane stresssigma_zz = lamb*(eps_xx+eps_yy)is not included). Bear this in mind when comparing 2D elastic “pressure” to the acoustic propagator’s pressure or to a 3D run.receiver_amplitudes_z: Recorded z-component velocity data, with units of velocity. The samples correspond to times (t-0.5)*dt (if ndim == 3).
receiver_amplitudes_y: Recorded y-component velocity data, with units of velocity. The samples correspond to times (t-0.5)*dt (if ndim >= 2).
receiver_amplitudes_x: Recorded x-component velocity data, with units of velocity. The samples correspond to times (t-0.5)*dt.
The receiver outputs are returned in the order pressure (p) first, followed by the velocity components (z, y, x, for the dimensions present), matching the order the propagator returns them in the output tuple.
This positional order is easy to index incorrectly (
out[-1]is the x-component velocity receiver amplitudes, not the pressure data); prefer accessing the fields by name instead: the wavefields use their initial-state names (vz_0,sigmazz_0, …,m_sigmaxxx_0) and the receiver amplitudes are exposed asreceiver_amplitudes_p,receiver_amplitudes_z,receiver_amplitudes_y, andreceiver_amplitudes_x.- Return type:
ElasticBorn Class¶
Born (linearised) modelling for the isotropic elastic wave equation. The background field solves the ordinary elastic system for lamb/mu/buoyancy, while the scattered field is the exact first-order linearisation for the perturbations dlamb/dmu/dbuoyancy. This is the elastic analogue of LSRTM and the linear map differentiated in elastic FWI. The scattered receiver data is linear in that (dlamb, dmu, dbuoyancy) scattering. See Born Modelling with the Elastic Wave Equation for the physics (and Born Modelling with the Scalar Wave Equation for the background theory of Born modelling in general) and Derivation: isotropic elastic Born (linearised) propagator for this propagator’s discrete derivation and its adjoint.
- class deepwave.ElasticBorn(lamb: Tensor, mu: Tensor, buoyancy: Tensor, grid_spacing: float | Sequence[float], *, dlamb: Tensor | None = None, dmu: Tensor | None = None, dbuoyancy: Tensor | None = None, requires_grad: bool | Sequence[str] | None = None, lamb_requires_grad: bool | None = None, mu_requires_grad: bool | None = None, buoyancy_requires_grad: bool | None = None, dlamb_requires_grad: bool | None = None, dmu_requires_grad: bool | None = None, dbuoyancy_requires_grad: bool | None = None, storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None)¶
A Module wrapper around
elastic_born().Stability: experimental (see Stability policy).
Stores
lamb, mu, buoyancy, grid_spacing(and, if desired,dlamb/dmu/dbuoyancy), matchingelastic.Elasticandacoustic_born.AcousticBorn. As in the functionalelastic_born(), at least one ofdlamb/dmu/dbuoyancymust be provided (the others default toNone, treated as zero perturbations); the module defers this validation toelastic_born()itself, which is called on everyforward().Deepwave orders spatial dimensions from slowest-varying to fastest-varying and attaches no physical meaning to any of them; the component suffixes count from the fastest axis, so a 2-D run uses
_yand_xand a 3-D run uses_z,_yand_x. See Dimension order and the axis convention.- Parameters:
lamb – The background first Lamé parameter model, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.mu – The background second Lamé parameter model, mu, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.buoyancy – The background buoyancy (1/density) model. A cell with
buoyancy = 0is a vacuum, not an infinitely dense cell; see the vacuum sentinel in Boundary conditions, which also explains how the sentinel is averaged onto the staggered nodes. It is of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.grid_spacing – The spatial grid cell size. It can be a single number (for isotropic grids) or a sequence of numbers (for anisotropic grids).
dlamb – The perturbation to the first Lamé parameter, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models. At least one of dlamb/dmu/dbuoyancy must be provided.dmu – The perturbation to the second Lamé parameter, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models. At least one of dlamb/dmu/dbuoyancy must be provided.dbuoyancy – The perturbation to the buoyancy, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models. At least one of dlamb/dmu/dbuoyancy must be provided.requires_grad – Which of this module’s models require a gradient.
None(the default) andFalseselect none,Trueselects every model this module owns, and a sequence of model names selects exactly those. Naming a model this class does not have, or an optional model that was not supplied, raisesValueError. It is an alternative spelling for the<model>_requires_gradflags below, each of which is unset (None) by default and then meansFalse. Passing it together with an individual flag that was given explicitly raisesValueErrorrather than letting one silently win – whichever way the two point, and even when they agree, so that there is one rule rather than a direction-dependent one.lamb_requires_grad – A bool specifying whether gradients will be computed for lamb. Unset by default, which means False. Cannot be combined with requires_grad.
mu_requires_grad – A bool specifying whether gradients will be computed for mu. Unset by default, which means False. Cannot be combined with requires_grad.
buoyancy_requires_grad – A bool specifying whether gradients will be computed for buoyancy. Unset by default, which means False. Cannot be combined with requires_grad.
dlamb_requires_grad – A bool specifying whether gradients will be computed for dlamb. Unset by default, which means False. Cannot be combined with requires_grad.
dmu_requires_grad – A bool specifying whether gradients will be computed for dmu. Unset by default, which means False. Cannot be combined with requires_grad.
dbuoyancy_requires_grad – A bool specifying whether gradients will be computed for dbuoyancy. Unset by default, which means False. Cannot be combined with requires_grad.
storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated. Compiled backend only. The forward allocates these store slots whenever a model requires grad, so a large allocation happens in the forward; “none” behaves as for
deepwave.acoustic_born().storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated. Compiled backend only.
storage_compression – Lossy – changes the model gradient by about 0.2-4% in 2-D and 0.2-8% in 3-D. See
deepwave.elastic(). Compiled backend only.
- Model ownership and gradients
Every model tensor given to the constructor is wrapped in a new
torch.nn.Parameterthat this module owns. The Parameter is a distinct leaf tensor that shares storage with the tensor you passed in: it is not a copy, so an in-place edit of one is visible in the other, but it is not the same object. Gradients therefore accumulate on the module’s own attribute (module.<model>.grad) and never on the tensor you passed in. A model requires a gradient only if you ask for one, through the constructor’srequires_gradargument or by callingmodule.<model>.requires_grad_(True)afterwards; handmodule.parameters()to atorch.optimoptimiser as usual. An optional model left asNoneis not a Parameter at all, so it appears in neitherparameters()norstate_dict(); assigning a tensor to that attribute later stores a plain tensor rather than registering a Parameter, so it stays out ofparameters()andstate_dict()(and out of any checkpoint) – give the model to the constructor, or wrap it yourself intorch.nn.Parameter. Because the module owns a leaf Parameter, it cannot carry an upstream autograd graph: if the model is itself produced by another operation – a network mapping a latent vector to a wavespeed, a reparameterisation, a smoothing filter – wrapping it in a module severs that graph and no gradient reaches the producer. Use the functional interface for anything graph-producing; it takes the model as an ordinary tensor argument and backpropagates through it.
Initialises the Module.
- forward(dt: float, *, sources: Mapping[str, tuple[Tensor, Tensor | Hicks] | tuple[Tensor, Tensor | Hicks, Tensor | None]] | None = None, receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, bg_receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, source_amplitudes_pressure_rate: Tensor | None = None, source_amplitudes_z: Tensor | None = None, source_amplitudes_y: Tensor | None = None, source_amplitudes_x: Tensor | None = None, source_locations_pressure_rate: Tensor | Hicks | None = None, source_locations_z: Tensor | Hicks | None = None, source_locations_y: Tensor | Hicks | None = None, source_locations_x: Tensor | Hicks | None = None, source_mask_pressure_rate: Tensor | None = None, source_mask_z: Tensor | None = None, source_mask_y: Tensor | None = None, source_mask_x: Tensor | None = None, bg_receiver_locations_p: Tensor | Hicks | None = None, bg_receiver_locations_z: Tensor | Hicks | None = None, bg_receiver_locations_y: Tensor | Hicks | None = None, bg_receiver_locations_x: Tensor | Hicks | None = None, bg_receiver_mask_p: Tensor | None = None, bg_receiver_mask_z: Tensor | None = None, bg_receiver_mask_y: Tensor | None = None, bg_receiver_mask_x: Tensor | None = None, sc_receiver_locations_p: Tensor | Hicks | None = None, sc_receiver_locations_z: Tensor | Hicks | None = None, sc_receiver_locations_y: Tensor | Hicks | None = None, sc_receiver_locations_x: Tensor | Hicks | None = None, sc_receiver_mask_p: Tensor | None = None, sc_receiver_mask_z: Tensor | None = None, sc_receiver_mask_y: Tensor | None = None, sc_receiver_mask_x: Tensor | None = None, vz_0: Tensor | None = None, vy_0: Tensor | None = None, vx_0: Tensor | None = None, sigmazz_0: Tensor | None = None, sigmayz_0: Tensor | None = None, sigmaxz_0: Tensor | None = None, sigmayy_0: Tensor | None = None, sigmaxy_0: Tensor | None = None, sigmaxx_0: Tensor | None = None, vz_sc_0: Tensor | None = None, vy_sc_0: Tensor | None = None, vx_sc_0: Tensor | None = None, sigmazz_sc_0: Tensor | None = None, sigmayz_sc_0: Tensor | None = None, sigmaxz_sc_0: Tensor | None = None, sigmayy_sc_0: Tensor | None = None, sigmaxy_sc_0: Tensor | None = None, sigmaxx_sc_0: Tensor | None = None, initial_state: PropagatorOutput | Mapping[str, Tensor | AuxiliaryState] | None = None, accuracy: Literal[2, 4, 6, 8] = 4, pml_width: int | Sequence[int] = 20, boundary: str | Sequence[str] | None = None, pml_freq: float | None = None, mpml_fraction: float = 0.0, max_vel: float | None = None, courant_number: float | None = None, survey_pad: int | Sequence[int | None] | None = None, origin: Sequence[int] | None = None, nt: int | None = None, model_gradient_sampling_interval: int = 1, checkpoint_segments: int | None = None, freq_taper_frac: float = 0.0, time_pad_frac: float = 0.0, time_taper: bool = False, check_output_finite: bool = True, forward_callback: Callback | None = None, backward_callback: Callback | None = None, callback_frequency: int = 1, backend: str = 'auto', storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None, location_interpolation: Literal['auto', 'hicks', 'none'] = 'auto', location_interpolation_halfwidth: int = 4) PropagatorOutput¶
Perform forward propagation/modelling.
See
elastic_born()for the meaning of every argument (the constructor-ownedlamb/mu/buoyancy/dlamb/dmu/dbuoyancy/grid_spacingand the storage settings are supplied from the stored module state).- Parameters:
dt – Time step interval. See
deepwave.elastic()for the unit-consistency requirement acrosslamb/mu/buoyancy/grid_spacing/dt.source_amplitudes_z – Shared z-force-density source amplitudes (both fields), with units of force/volume as in
deepwave.elastic(). To drive the propagation with a volumetric (extended) source instead of hand-placed point sources, build the amplitudes and integer locations withdeepwave.wavefields.source_field_to_sources(). This channel exists only in 3-D.source_amplitudes_y – Shared y-force-density source amplitudes.
source_amplitudes_x – Shared x-force-density source amplitudes.
sources – This simulation’s sources, keyed by channel. This is the canonical way to specify a survey. Each value is
(amplitudes, locations), or(amplitudes, locations, mask)to include an activity mask. The channels arepressure_rate,z,y,x(zonly in 3-D,yonly in 2-D and 3-D); these are equivalent to the flatsource_amplitudes_*/source_locations_*keywords, which remain permanently supported; giving one channel in both forms raises. Optional.receivers – This simulation’s receivers, keyed by channel, as the canonical alternative to the flat
sc_receiver_locations*keywords. Each value is a locations object, or(locations, mask)to include an activity mask. The channels arep,z,y,x(zonly in 3-D,yonly in 2-D and 3-D). Giving one channel in both forms raises. Optional.bg_receivers – The receivers that record the background wavefield, keyed by channel, as the canonical alternative to the flat
bg_receiver_locations*keywords. Values take the same forms asreceivers’. Giving one channel in both forms raises. Optional.source_amplitudes_pressure_rate – Shared pressure-rate source amplitudes, with units of pressure/time as in
deepwave.elastic()(not the volume-injection rate of the acoustic family; see Units and source conventions).source_locations_z – z-force source locations (integer grid indices). This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_y – y-force source locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_x – x-force source locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_pressure_rate – Pressure source locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_mask_pressure_rate – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
pressure_ratechannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_pressure_rateare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_pressure_rate, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_z – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_y – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
ychannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_x – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
xchannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_locations_z – Scattered-field z-velocity receiver locations. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_locations_y – Scattered-field y-velocity receiver locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_locations_x – Scattered-field x-velocity receiver locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_locations_p – Scattered-field pressure receiver locations. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_locations_z – Optional background z-velocity receivers. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_locations_y – Optional background y-velocity receivers. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_locations_x – Optional background x-velocity receivers. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_locations_p – Optional background pressure receivers. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.vz_0 – Initial background vz wavefield, as in
deepwave.elastic().vy_0 – Initial background vy wavefield.
vx_0 – Initial background vx wavefield.
sigmazz_0 – Initial background sigmazz wavefield.
sigmayz_0 – Initial background sigmayz wavefield.
sigmaxz_0 – Initial background sigmaxz wavefield.
sigmayy_0 – Initial background sigmayy wavefield.
sigmaxy_0 – Initial background sigmaxy wavefield.
sigmaxx_0 – Initial background sigmaxx wavefield.
vz_sc_0 – Initial scattered vz wavefield.
vy_sc_0 – Initial scattered vy wavefield.
vx_sc_0 – Initial scattered vx wavefield.
sigmazz_sc_0 – Initial scattered sigmazz wavefield.
sigmayz_sc_0 – Initial scattered sigmayz wavefield.
sigmaxz_sc_0 – Initial scattered sigmaxz wavefield.
sigmayy_sc_0 – Initial scattered sigmayy wavefield.
sigmaxy_sc_0 – Initial scattered sigmaxy wavefield.
sigmaxx_sc_0 – Initial scattered sigmaxx wavefield.
accuracy – See
deepwave.elastic().pml_width – See
deepwave.elastic(). A face whosepml_widthis zero does not absorb: it becomes an implicit reflecting boundary whose type depends on the propagator and the field component. See Reflecting edges for the per-propagator reflection coefficient and surface location, and prefer naming the condition withboundary(ordeepwave.boundaries()), which also uses the exact image rather than this approximate one.boundary – An optional single string, applying to every face, or a list of 2 * ndim strings selecting a first-class boundary condition per face, in the same order as pml_width and with the same semantics as
deepwave.elastic()’s boundary (“pml”, “free”, “rigid”, or “periodic”; a non-“pml” face requires pml_width == 0 on that face). Applied independently to the background field (v, sigma) and the scattered field (dv, dsigma): both obey the identical isotropic elastic staggered- grid system on the same grid (see the module docstring), so the same per-field image parity (the flat-face parity table documented on deepwave.elastic) applies to each independently, with no new physics beyond whatdeepwave.elastic()already validates. Validated on the eager (backend=”eager”) and the default compiled C/CUDA backends; the “torch_compile” Python mode shares the eager guard-fill code path but is not separately validated for boundary=. Availability: “pml” is accepted on every face at every accuracy, and “rigid” on the beginning of a dimension at every accuracy and on the end of a dimension at accuracy=2. “rigid” on the end of a dimension with accuracy >= 4, and “free” and “periodic” on any face, raisedeepwave.DeepwaveNotImplementedError: those guard-ring fills do not conserve a discrete energy, so the solution can grow without bound. Model a free surface with a vacuum layer (the improved vacuum method) instead; put a “rigid” face at the beginning of the dimension (flip the model along that axis), or use accuracy=2. Faces may be accepted in a later release; none is removed.pml_freq – See
deepwave.elastic().mpml_fraction – Multiaxial-PML fraction, as in
deepwave.elastic().max_vel – See
deepwave.elastic().courant_number – See
deepwave.elastic().survey_pad – See
deepwave.scalar().initial_state – See
deepwave.elastic(). The mapping keys are this propagator’s own public state field names – the background names ofdeepwave.elastic()(e.g. vz_0) and the scattered names, which carry sc before the time index (e.g. vz_sc_0) – plus auxiliary_state. The individual absorbing-boundary field names (m_vzz_0, … and their scattered counterparts) are not accepted as keys: pass initial_state=out (or initial_state=out.final_state) to carry them across.origin – See
deepwave.scalar().nt – See
deepwave.elastic().model_gradient_sampling_interval – See
deepwave.elastic().checkpoint_segments –
If given, split the time axis into this many segments and run each of them under
torch.utils.checkpoint, which is the memory lever for a run whose wavefield history does not fit: peak backward memory falls to roughly one segment’s history plus the states held at the segment boundaries, at the cost of running the forward pass of each segment a second time during the backward pass. None (the default) runs the whole time axis in one piece, exactly as before. It is the same thing as callingdeepwave.checkpointing.run_segments()withn_segments=andcheckpoint=True, and returns the same combined output – the same fields, the same info and the same auxiliary_state a direct call gives. initial_state, the storage arguments and every physics option are supported; nt may pad or truncate supplied source amplitudes for the whole run. Source-free nt calls, individual initial-wavefield arguments and per-step callbacks are not supported, and say so.Take the gradient with
loss.backward(). The checkpointing is reentrant, andtorch.utils.checkpointdoes not supporttorch.autograd.grad()(or aninputs=argument to.backward()) in that mode: it raises. If you needtorch.autograd.grad, calldeepwave.checkpointing.run_segments()directly withuse_reentrant=False.freq_taper_frac – See
deepwave.elastic().time_pad_frac – See
deepwave.elastic().time_taper – See
deepwave.elastic().check_output_finite – See
deepwave.elastic().forward_callback – See
deepwave.elastic(). Supported on both the default compiled backend and the eager backend (backend= "eager").backward_callback – See
deepwave.elastic(). Compiled backend only.callback_frequency – See
deepwave.elastic().backend – Which execution backend to use:
"auto"(the default),"compiled","eager"or"torch_compile". See Backends for what each value selects, what"auto"resolves to, and how the backends agree numerically."auto"uses the compiled C/CUDA forward, paired with the compiled adjoint kernels, on CPU and on CUDA alike;out.info.backward_backendreports which backend the backward pass would use, and currently always matchesout.info.backend. The compiled backend has no M-PML forward kernel, so a call withmpml_fraction > 0is one whose options only the eager backend implements:"auto"resolves to"eager"for it (andout.info.backendsays so), which is much slower, while"compiled"raisesdeepwave.DeepwaveNotImplementedErrorbecause that spelling asserts the compiled kernel ran.storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated. Compiled backend only. The forward allocates these store slots whenever a model requires grad, so a large allocation happens in the forward; “none” behaves as for
deepwave.acoustic_born().storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated. Compiled backend only.
storage_compression – Lossy – changes the model gradient by about 0.2-4% in 2-D and 0.2-8% in 3-D. See
deepwave.elastic(). Compiled backend only.location_interpolation – See
deepwave.elastic(). A single source interpolator is built from the shared source locations and its spread applied once, then shared by the background and the (internally derived) scattered source – both drive the same physical locations (see the module docstring’s source-cell paragraph). The background and scattered receivers have independent interpolators."auto"interpolates a floating-point locations Tensor only when at least one non-ignored coordinate lies more thandeepwave.ON_NODE_TOLERANCEcells off its component’s grid node – except that a floating-point Tensor withrequires_grad=Trueis always interpolated, even when every coordinate is on-node, because only the interpolated path carries gradients back to the positions. That changes the forward values for an on-noderequires_gradlocations Tensor relative to the same Tensor withoutrequires_grad. Passlocation_interpolation="none"for the exact path (positions are then not differentiable), or accept the band-limited values.RunInfo.location_interpolation_usedrecords which path was taken:"none"or"hicks", or"mixed"if this propagator has several channels of one kind (several source components, say) and they did not all take the same path.location_interpolation_halfwidth – See
deepwave.elastic().
ElasticBorn Function¶
- deepwave.elastic_born(lamb: Tensor, mu: Tensor, buoyancy: Tensor, grid_spacing: float | Sequence[float], dt: float, *, dlamb: Tensor | None = None, dmu: Tensor | None = None, dbuoyancy: Tensor | None = None, sources: Mapping[str, tuple[Tensor, Tensor | Hicks] | tuple[Tensor, Tensor | Hicks, Tensor | None]] | None = None, receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, bg_receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, source_amplitudes_pressure_rate: Tensor | None = None, source_amplitudes_z: Tensor | None = None, source_amplitudes_y: Tensor | None = None, source_amplitudes_x: Tensor | None = None, source_locations_pressure_rate: Tensor | Hicks | None = None, source_locations_z: Tensor | Hicks | None = None, source_locations_y: Tensor | Hicks | None = None, source_locations_x: Tensor | Hicks | None = None, source_mask_pressure_rate: Tensor | None = None, source_mask_z: Tensor | None = None, source_mask_y: Tensor | None = None, source_mask_x: Tensor | None = None, bg_receiver_locations_p: Tensor | Hicks | None = None, bg_receiver_locations_z: Tensor | Hicks | None = None, bg_receiver_locations_y: Tensor | Hicks | None = None, bg_receiver_locations_x: Tensor | Hicks | None = None, bg_receiver_mask_p: Tensor | None = None, bg_receiver_mask_z: Tensor | None = None, bg_receiver_mask_y: Tensor | None = None, bg_receiver_mask_x: Tensor | None = None, sc_receiver_locations_p: Tensor | Hicks | None = None, sc_receiver_locations_z: Tensor | Hicks | None = None, sc_receiver_locations_y: Tensor | Hicks | None = None, sc_receiver_locations_x: Tensor | Hicks | None = None, sc_receiver_mask_p: Tensor | None = None, sc_receiver_mask_z: Tensor | None = None, sc_receiver_mask_y: Tensor | None = None, sc_receiver_mask_x: Tensor | None = None, vz_0: Tensor | None = None, vy_0: Tensor | None = None, vx_0: Tensor | None = None, sigmazz_0: Tensor | None = None, sigmayz_0: Tensor | None = None, sigmaxz_0: Tensor | None = None, sigmayy_0: Tensor | None = None, sigmaxy_0: Tensor | None = None, sigmaxx_0: Tensor | None = None, vz_sc_0: Tensor | None = None, vy_sc_0: Tensor | None = None, vx_sc_0: Tensor | None = None, sigmazz_sc_0: Tensor | None = None, sigmayz_sc_0: Tensor | None = None, sigmaxz_sc_0: Tensor | None = None, sigmayy_sc_0: Tensor | None = None, sigmaxy_sc_0: Tensor | None = None, sigmaxx_sc_0: Tensor | None = None, initial_state: PropagatorOutput | Mapping[str, Tensor | AuxiliaryState] | None = None, accuracy: Literal[2, 4, 6, 8] = 4, pml_width: int | Sequence[int] = 20, boundary: str | Sequence[str] | None = None, pml_freq: float | None = None, mpml_fraction: float = 0.0, max_vel: float | None = None, courant_number: float | None = None, survey_pad: int | Sequence[int | None] | None = None, origin: Sequence[int] | None = None, nt: int | None = None, model_gradient_sampling_interval: int = 1, checkpoint_segments: int | None = None, freq_taper_frac: float = 0.0, time_pad_frac: float = 0.0, time_taper: bool = False, check_output_finite: bool = True, forward_callback: Callback | None = None, backward_callback: Callback | None = None, callback_frequency: int = 1, backend: str = 'auto', storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None, location_interpolation: Literal['auto', 'hicks', 'none'] = 'auto', location_interpolation_halfwidth: int = 4) PropagatorOutput¶
Isotropic elastic Born (linearised) wave propagation.
Stability: experimental (see Stability policy).
The background field solves the ordinary (nonlinear) isotropic elastic system for
(lamb, mu, buoyancy); the scattered field is the exact first-order linearisation for perturbations(dlamb, dmu, dbuoyancy), driven by virtual sources built from the background field’s own strain-rate / stress-divergence terms times the scattering models (seedocs/elastic_born_derivation.md). A single set of source amplitudes per component drives both fields; the scattered field is automatically driven by the velocity/force “source-cell” termdt * dbuoyancy_i(the pressure source, pre-scaled by-dtwith no model factor, carries no model perturbation and so contributes no scattered source; the derivation is indocs/elastic_born_derivation.md, under the scattered-source section).Current scope. The default,
backend="auto", runs the compiled C/CUDA forward, and uses the compiled adjoint kernels for backpropagation on both CPU and CUDA; under M-PML (mpml_fraction > 0) the compiled forward is not yet available and the call raises rather than falling back (seedocs/elastic_born_derivation.mdSS8-10). Passingbackend="eager"selects the pure-PyTorch backend for both forward and backward;"torch_compile"runs the same eager time loop with the two coupled step functions compiled. The true Hessian-vector product andtorch.func.jvprouting remain follow-up work. Both backends support float/Hicks source-receiver interpolation (location_interpolation), as indeepwave.elastic(). Gradients w.r.t.lamb, mu, buoyancy, dlamb, dmu, dbuoyancy, source amplitudes, and initial wavefields are all supported through ordinary autograd.Deepwave orders spatial dimensions from slowest-varying to fastest-varying and attaches no physical meaning to any of them; the component suffixes count from the fastest axis, so a 2-D run uses
_yand_xand a 3-D run uses_z,_yand_x. See Dimension order and the axis convention.- Parameters:
lamb – The background first Lame parameter model (see
deepwave.elastic()), of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.mu – The background shear modulus model, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.buoyancy – The background buoyancy (1/density) model. A cell with
buoyancy = 0is a vacuum, not an infinitely dense cell; see the vacuum sentinel in Boundary conditions, which also explains how the sentinel is averaged onto the staggered nodes. It is of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.grid_spacing – Spatial grid cell size.
dt – Time step interval. See
deepwave.elastic()for the unit-consistency requirement acrosslamb/mu/buoyancy/grid_spacing/dt.dlamb – The
lambscattering perturbation model (None-> zero), of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.dmu – The
muscattering perturbation model (None-> zero), of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.dbuoyancy – The
buoyancyscattering perturbation model (None-> zero), of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.source_amplitudes_z – Shared z-force-density source amplitudes (both fields), with units of force/volume as in
deepwave.elastic(). To drive the propagation with a volumetric (extended) source instead of hand-placed point sources, build the amplitudes and integer locations withdeepwave.wavefields.source_field_to_sources(). This channel exists only in 3-D.source_amplitudes_y – Shared y-force-density source amplitudes.
source_amplitudes_x – Shared x-force-density source amplitudes.
sources – This simulation’s sources, keyed by channel. This is the canonical way to specify a survey. Each value is
(amplitudes, locations), or(amplitudes, locations, mask)to include an activity mask. The channels arepressure_rate,z,y,x(zonly in 3-D,yonly in 2-D and 3-D); these are equivalent to the flatsource_amplitudes_*/source_locations_*keywords, which remain permanently supported; giving one channel in both forms raises. Optional.receivers – This simulation’s receivers, keyed by channel, as the canonical alternative to the flat
sc_receiver_locations*keywords. Each value is a locations object, or(locations, mask)to include an activity mask. The channels arep,z,y,x(zonly in 3-D,yonly in 2-D and 3-D). Giving one channel in both forms raises. Optional.bg_receivers – The receivers that record the background wavefield, keyed by channel, as the canonical alternative to the flat
bg_receiver_locations*keywords. Values take the same forms asreceivers’. Giving one channel in both forms raises. Optional.source_amplitudes_pressure_rate – Shared pressure-rate source amplitudes, with units of pressure/time as in
deepwave.elastic()(not the volume-injection rate of the acoustic family; see Units and source conventions).source_locations_z – z-force source locations (integer grid indices). This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_y – y-force source locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_x – x-force source locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_pressure_rate – Pressure source locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_mask_pressure_rate – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
pressure_ratechannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_pressure_rateare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_pressure_rate, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_z – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_y – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
ychannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_x – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
xchannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_locations_z – Scattered-field z-velocity receiver locations. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_locations_y – Scattered-field y-velocity receiver locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_locations_x – Scattered-field x-velocity receiver locations. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_locations_p – Scattered-field pressure receiver locations. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.sc_receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.sc_receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates insc_receiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsc_receiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_locations_z – Optional background z-velocity receivers. This channel exists only in 3-D. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_locations_y – Optional background y-velocity receivers. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_locations_x – Optional background x-velocity receivers. A point whose coordinates are all
deepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_locations_p – Optional background pressure receivers. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.bg_receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.bg_receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel recording the background wavefield are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inbg_receiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofbg_receiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.vz_0 – Initial background vz wavefield, as in
deepwave.elastic().vy_0 – Initial background vy wavefield.
vx_0 – Initial background vx wavefield.
sigmazz_0 – Initial background sigmazz wavefield.
sigmayz_0 – Initial background sigmayz wavefield.
sigmaxz_0 – Initial background sigmaxz wavefield.
sigmayy_0 – Initial background sigmayy wavefield.
sigmaxy_0 – Initial background sigmaxy wavefield.
sigmaxx_0 – Initial background sigmaxx wavefield.
vz_sc_0 – Initial scattered vz wavefield.
vy_sc_0 – Initial scattered vy wavefield.
vx_sc_0 – Initial scattered vx wavefield.
sigmazz_sc_0 – Initial scattered sigmazz wavefield.
sigmayz_sc_0 – Initial scattered sigmayz wavefield.
sigmaxz_sc_0 – Initial scattered sigmaxz wavefield.
sigmayy_sc_0 – Initial scattered sigmayy wavefield.
sigmaxy_sc_0 – Initial scattered sigmaxy wavefield.
sigmaxx_sc_0 – Initial scattered sigmaxx wavefield.
accuracy – See
deepwave.elastic().pml_width – See
deepwave.elastic(). A face whosepml_widthis zero does not absorb: it becomes an implicit reflecting boundary whose type depends on the propagator and the field component. See Reflecting edges for the per-propagator reflection coefficient and surface location, and prefer naming the condition withboundary(ordeepwave.boundaries()), which also uses the exact image rather than this approximate one.boundary – An optional single string, applying to every face, or a list of 2 * ndim strings selecting a first-class boundary condition per face, in the same order as pml_width and with the same semantics as
deepwave.elastic()’s boundary (“pml”, “free”, “rigid”, or “periodic”; a non-“pml” face requires pml_width == 0 on that face). Applied independently to the background field (v, sigma) and the scattered field (dv, dsigma): both obey the identical isotropic elastic staggered- grid system on the same grid (see the module docstring), so the same per-field image parity (the flat-face parity table documented on deepwave.elastic) applies to each independently, with no new physics beyond whatdeepwave.elastic()already validates. Validated on the eager (backend=”eager”) and the default compiled C/CUDA backends; the “torch_compile” Python mode shares the eager guard-fill code path but is not separately validated for boundary=. Availability: “pml” is accepted on every face at every accuracy, and “rigid” on the beginning of a dimension at every accuracy and on the end of a dimension at accuracy=2. “rigid” on the end of a dimension with accuracy >= 4, and “free” and “periodic” on any face, raisedeepwave.DeepwaveNotImplementedError: those guard-ring fills do not conserve a discrete energy, so the solution can grow without bound. Model a free surface with a vacuum layer (the improved vacuum method) instead; put a “rigid” face at the beginning of the dimension (flip the model along that axis), or use accuracy=2. Faces may be accepted in a later release; none is removed.pml_freq – See
deepwave.elastic().mpml_fraction – Multiaxial-PML fraction, as in
deepwave.elastic().max_vel – See
deepwave.elastic().courant_number – See
deepwave.elastic().survey_pad – See
deepwave.scalar().initial_state – See
deepwave.elastic(). The mapping keys are this propagator’s own public state field names – the background names ofdeepwave.elastic()(e.g. vz_0) and the scattered names, which carry sc before the time index (e.g. vz_sc_0) – plus auxiliary_state. The individual absorbing-boundary field names (m_vzz_0, … and their scattered counterparts) are not accepted as keys: pass initial_state=out (or initial_state=out.final_state) to carry them across.origin – See
deepwave.scalar().nt – See
deepwave.elastic().model_gradient_sampling_interval – See
deepwave.elastic().checkpoint_segments –
If given, split the time axis into this many segments and run each of them under
torch.utils.checkpoint, which is the memory lever for a run whose wavefield history does not fit: peak backward memory falls to roughly one segment’s history plus the states held at the segment boundaries, at the cost of running the forward pass of each segment a second time during the backward pass. None (the default) runs the whole time axis in one piece, exactly as before. It is the same thing as callingdeepwave.checkpointing.run_segments()withn_segments=andcheckpoint=True, and returns the same combined output – the same fields, the same info and the same auxiliary_state a direct call gives. initial_state, the storage arguments and every physics option are supported; nt may pad or truncate supplied source amplitudes for the whole run. Source-free nt calls, individual initial-wavefield arguments and per-step callbacks are not supported, and say so.Take the gradient with
loss.backward(). The checkpointing is reentrant, andtorch.utils.checkpointdoes not supporttorch.autograd.grad()(or aninputs=argument to.backward()) in that mode: it raises. If you needtorch.autograd.grad, calldeepwave.checkpointing.run_segments()directly withuse_reentrant=False.freq_taper_frac – See
deepwave.elastic().time_pad_frac – See
deepwave.elastic().time_taper – See
deepwave.elastic().check_output_finite – See
deepwave.elastic().forward_callback – See
deepwave.elastic(). Supported on both the default compiled backend and the eager backend (backend= "eager").backward_callback – See
deepwave.elastic(). Compiled backend only.callback_frequency – See
deepwave.elastic().backend – Which execution backend to use:
"auto"(the default),"compiled","eager"or"torch_compile". See Backends for what each value selects, what"auto"resolves to, and how the backends agree numerically."auto"uses the compiled C/CUDA forward, paired with the compiled adjoint kernels, on CPU and on CUDA alike;out.info.backward_backendreports which backend the backward pass would use, and currently always matchesout.info.backend. The compiled backend has no M-PML forward kernel, so a call withmpml_fraction > 0is one whose options only the eager backend implements:"auto"resolves to"eager"for it (andout.info.backendsays so), which is much slower, while"compiled"raisesdeepwave.DeepwaveNotImplementedErrorbecause that spelling asserts the compiled kernel ran.storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated. Compiled backend only. The forward allocates these store slots whenever a model requires grad, so a large allocation happens in the forward; “none” behaves as for
deepwave.acoustic_born().storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated. Compiled backend only.
storage_compression – Lossy – changes the model gradient by about 0.2-4% in 2-D and 0.2-8% in 3-D. See
deepwave.elastic(). Compiled backend only.location_interpolation – See
deepwave.elastic(). A single source interpolator is built from the shared source locations and its spread applied once, then shared by the background and the (internally derived) scattered source – both drive the same physical locations (see the module docstring’s source-cell paragraph). The background and scattered receivers have independent interpolators."auto"interpolates a floating-point locations Tensor only when at least one non-ignored coordinate lies more thandeepwave.ON_NODE_TOLERANCEcells off its component’s grid node – except that a floating-point Tensor withrequires_grad=Trueis always interpolated, even when every coordinate is on-node, because only the interpolated path carries gradients back to the positions. That changes the forward values for an on-noderequires_gradlocations Tensor relative to the same Tensor withoutrequires_grad. Passlocation_interpolation="none"for the exact path (positions are then not differentiable), or accept the band-limited values.RunInfo.location_interpolation_usedrecords which path was taken:"none"or"hicks", or"mixed"if this propagator has several channels of one kind (several source components, say) and they did not all take the same path.location_interpolation_halfwidth – See
deepwave.elastic().
- Returns:
a tuple subclass whose fields, in order, are:
vz_0: Final background z-velocity wavefield (if ndim == 3).
vy_0: Final background y-velocity wavefield (if ndim >= 2).
vx_0: Final background x-velocity wavefield.
sigmazz_0: Final background zz-stress wavefield (if ndim == 3).
sigmayz_0: Final background yz-stress wavefield (if ndim == 3).
sigmaxz_0: Final background xz-stress wavefield (if ndim == 3).
sigmayy_0: Final background yy-stress wavefield (if ndim >= 2).
sigmaxy_0: Final background xy-stress wavefield (if ndim >= 2).
sigmaxx_0: Final background xx-stress wavefield.
auxiliary_state: A
deepwave.AuxiliaryStateholding the absorbing boundary’s memory variables, of both the background and the scattered field. Opaque: pass it back (as part of initial_state) to continue the simulation; its contents are implementation state rather than physics.vz_sc_0: Final scattered z-velocity wavefield (if ndim == 3).
vy_sc_0: Final scattered y-velocity wavefield (if ndim >= 2).
vx_sc_0: Final scattered x-velocity wavefield.
sigmazz_sc_0: Final scattered zz-stress wavefield (if ndim == 3).
sigmayz_sc_0: Final scattered yz-stress wavefield (if ndim == 3).
sigmaxz_sc_0: Final scattered xz-stress wavefield (if ndim == 3).
sigmayy_sc_0: Final scattered yy-stress wavefield (if ndim >= 2).
sigmaxy_sc_0: Final scattered xy-stress wavefield (if ndim >= 2).
sigmaxx_sc_0: Final scattered xx-stress wavefield.
bg_receiver_amplitudes_p: Recorded background pressure data. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement.bg_receiver_amplitudes_z: Recorded background z-velocity data (if ndim == 3).
bg_receiver_amplitudes_y: Recorded background y-velocity data (if ndim >= 2).
bg_receiver_amplitudes_x: Recorded background x-velocity data.
sc_receiver_amplitudes_p: Recorded scattered pressure data. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement.sc_receiver_amplitudes_z: Recorded scattered z-velocity data (if ndim == 3).
sc_receiver_amplitudes_y: Recorded scattered y-velocity data (if ndim >= 2).
sc_receiver_amplitudes_x: Recorded scattered x-velocity data.
This positional order is easy to index incorrectly (
out[-1]is the scattered x-component velocity receiver amplitudes, not the pressure data); prefer accessing the receiver fields by name instead.- Return type:
Elastic VTI¶
- class deepwave.ElasticVti(c11: Tensor, c13: Tensor, c33: Tensor, c55: Tensor, buoyancy: Tensor, grid_spacing: float | Sequence[float], *, c66: Tensor | None = None, requires_grad: bool | Sequence[str] | None = None, c11_requires_grad: bool | None = None, c13_requires_grad: bool | None = None, c33_requires_grad: bool | None = None, c55_requires_grad: bool | None = None, buoyancy_requires_grad: bool | None = None, c66_requires_grad: bool | None = None, storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None)¶
A PyTorch Module for elastic VTI wave propagation.
Stability: experimental (see Stability policy).
This Module stores the VTI stiffnesses (
c11,c13,c33,c55, and, for 3-D,c66) and the buoyancy astorch.nn.Parameterobjects, allowing gradients to be computed with respect to them if desired.Deepwave orders spatial dimensions from slowest-varying to fastest-varying and attaches no physical meaning to any of them; the component suffixes count from the fastest axis, so a 2-D run uses
_yand_xand a 3-D run uses_z,_yand_x. See Dimension order and the axis convention. The one exception to that freedom is this family: its symmetry axis is dimension 0 by construction, so here the axis order is a physics constraint rather than a documentation convention.- Parameters:
c11 – The c11 stiffness model (horizontal P modulus), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c13 – The c13 stiffness model, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c33 – The c33 stiffness model (vertical P modulus), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c55 – The c55 stiffness model (shear modulus for planes containing the symmetry axis), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.buoyancy – The buoyancy (1/density) model. A cell with
buoyancy = 0is a vacuum, not an infinitely dense cell; see the vacuum sentinel in Boundary conditions, which also explains how the sentinel is averaged onto the staggered nodes. It is of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.grid_spacing – The spatial grid cell size. It can be a single number (for isotropic grids) or a sequence of numbers.
c66 – Required in 3-D; must be None in 2-D (it does not enter the 2-D P-SV equations). The c66 stiffness model (horizontal-plane shear modulus), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.requires_grad – Which of this module’s models require a gradient.
None(the default) andFalseselect none,Trueselects every model this module owns, and a sequence of model names selects exactly those. Naming a model this class does not have, or an optional model that was not supplied, raisesValueError. It is an alternative spelling for the<model>_requires_gradflags below, each of which is unset (None) by default and then meansFalse. Passing it together with an individual flag that was given explicitly raisesValueErrorrather than letting one silently win – whichever way the two point, and even when they agree, so that there is one rule rather than a direction-dependent one.c11_requires_grad – A bool specifying whether gradients will be computed for c11. Unset by default, which means False. Cannot be combined with requires_grad.
c13_requires_grad – A bool specifying whether gradients will be computed for c13. Unset by default, which means False. Cannot be combined with requires_grad.
c33_requires_grad – A bool specifying whether gradients will be computed for c33. Unset by default, which means False. Cannot be combined with requires_grad.
c55_requires_grad – A bool specifying whether gradients will be computed for c55. Unset by default, which means False. Cannot be combined with requires_grad.
buoyancy_requires_grad – A bool specifying whether gradients will be computed for buoyancy. Unset by default, which means False. Cannot be combined with requires_grad.
c66_requires_grad – A bool specifying whether gradients will be computed for c66. Unset by default, which means False. Cannot be combined with requires_grad.
storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated.
storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated.
storage_compression – Lossy – changes the model gradient by about 0.2-4% in 2-D and 0.2-8% in 3-D. See
deepwave.elastic().
- Model ownership and gradients
Every model tensor given to the constructor is wrapped in a new
torch.nn.Parameterthat this module owns. The Parameter is a distinct leaf tensor that shares storage with the tensor you passed in: it is not a copy, so an in-place edit of one is visible in the other, but it is not the same object. Gradients therefore accumulate on the module’s own attribute (module.<model>.grad) and never on the tensor you passed in. A model requires a gradient only if you ask for one, through the constructor’srequires_gradargument or by callingmodule.<model>.requires_grad_(True)afterwards; handmodule.parameters()to atorch.optimoptimiser as usual. An optional model left asNoneis not a Parameter at all, so it appears in neitherparameters()norstate_dict(); assigning a tensor to that attribute later stores a plain tensor rather than registering a Parameter, so it stays out ofparameters()andstate_dict()(and out of any checkpoint) – give the model to the constructor, or wrap it yourself intorch.nn.Parameter. Because the module owns a leaf Parameter, it cannot carry an upstream autograd graph: if the model is itself produced by another operation – a network mapping a latent vector to a wavespeed, a reparameterisation, a smoothing filter – wrapping it in a module severs that graph and no gradient reaches the producer. Use the functional interface for anything graph-producing; it takes the model as an ordinary tensor argument and backpropagates through it.
Initialises the Module.
- forward(dt: float, *, sources: Mapping[str, tuple[Tensor, Tensor | Hicks] | tuple[Tensor, Tensor | Hicks, Tensor | None]] | None = None, receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, source_amplitudes_pressure_rate: Tensor | None = None, source_amplitudes_z: Tensor | None = None, source_amplitudes_y: Tensor | None = None, source_amplitudes_x: Tensor | None = None, source_locations_pressure_rate: Tensor | Hicks | None = None, source_locations_z: Tensor | Hicks | None = None, source_locations_y: Tensor | Hicks | None = None, source_locations_x: Tensor | Hicks | None = None, source_mask_pressure_rate: Tensor | None = None, source_mask_z: Tensor | None = None, source_mask_y: Tensor | None = None, source_mask_x: Tensor | None = None, receiver_locations_p: Tensor | Hicks | None = None, receiver_locations_z: Tensor | Hicks | None = None, receiver_locations_y: Tensor | Hicks | None = None, receiver_locations_x: Tensor | Hicks | None = None, receiver_mask_p: Tensor | None = None, receiver_mask_z: Tensor | None = None, receiver_mask_y: Tensor | None = None, receiver_mask_x: Tensor | None = None, vz_0: Tensor | None = None, vy_0: Tensor | None = None, vx_0: Tensor | None = None, sigmazz_0: Tensor | None = None, sigmayz_0: Tensor | None = None, sigmaxz_0: Tensor | None = None, sigmayy_0: Tensor | None = None, sigmaxy_0: Tensor | None = None, sigmaxx_0: Tensor | None = None, initial_state: PropagatorOutput | Mapping[str, Tensor | AuxiliaryState] | None = None, accuracy: Literal[2, 4, 6, 8] = 4, pml_width: int | Sequence[int] = 20, boundary: str | Sequence[str] | None = None, pml_freq: float | None = None, mpml_fraction: float = 0.0, max_vel: float | None = None, courant_number: float | None = None, survey_pad: int | Sequence[int | None] | None = None, origin: Sequence[int] | None = None, nt: int | None = None, model_gradient_sampling_interval: int = 1, checkpoint_segments: int | None = None, freq_taper_frac: float = 0.0, time_pad_frac: float = 0.0, time_taper: bool = False, check_output_finite: bool = True, forward_callback: Callback | None = None, backward_callback: Callback | None = None, callback_frequency: int = 1, backend: str = 'auto', storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None, location_interpolation: Literal['auto', 'hicks', 'none'] = 'auto', location_interpolation_halfwidth: int = 4) PropagatorOutput¶
Perform forward propagation/modelling.
The inputs are the same as for
deepwave.elastic_vti()except that the stiffnesses, buoyancy, grid_spacing, and the storage settings (storage_mode/storage_path/storage_compression) do not need to be provided again – they are supplied from the stored module state. Seedeepwave.elastic_vti()for a description of the inputs and outputs.- Parameters:
dt – The time step interval of the input and output. See
deepwave.elastic()for the unit-consistency requirement (here applying to the stiffnesses,buoyancy,grid_spacing, anddt).source_amplitudes_z – See
deepwave.elastic(). This channel exists only in 3-D.source_amplitudes_y – See
deepwave.elastic().source_amplitudes_x – See
deepwave.elastic().sources – This simulation’s sources, keyed by channel. This is the canonical way to specify a survey. Each value is
(amplitudes, locations), or(amplitudes, locations, mask)to include an activity mask. The channels arepressure_rate,z,y,x(zonly in 3-D); these are equivalent to the flatsource_amplitudes_*/source_locations_*keywords, which remain permanently supported; giving one channel in both forms raises. Optional.receivers – This simulation’s receivers, keyed by channel, as the canonical alternative to the flat
receiver_locations*keywords. Each value is a locations object, or(locations, mask)to include an activity mask. The channels arep,z,y,x(zonly in 3-D). Giving one channel in both forms raises. Optional.source_amplitudes_pressure_rate – See
deepwave.elastic().source_locations_z – See
deepwave.elastic(). This channel exists only in 3-D. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_y – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_x – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_pressure_rate – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_mask_pressure_rate – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
pressure_ratechannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_pressure_rateare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_pressure_rate, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_z – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_y – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
ychannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_x – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
xchannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_locations_z – See
deepwave.elastic(). This channel exists only in 3-D. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_y – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_x – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_p – See
deepwave.elastic(). In 2-D the recorded pressure is the in-plane mean normal stress-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.accuracy – See
deepwave.elastic(). Default 4.pml_width – See
deepwave.elastic(). Default 20. A face whosepml_widthis zero does not absorb: it becomes an implicit reflecting boundary whose type depends on the propagator and the field component. See Reflecting edges for the per-propagator reflection coefficient and surface location, and prefer naming the condition withboundary(ordeepwave.boundaries()), which also uses the exact image rather than this approximate one.boundary – See
deepwave.elastic(). The same per-field free/rigid/periodic guard-ring image method; the physics/citation reasoning is unchanged by VTI’s stiffness (seedocs/boundaries.rst’s Policy section and_boundaries.py’sfill_elastic_stress_boundary/fill_elastic_velocity_boundarymodule comment). Availability: “pml” is accepted on every face at every accuracy, and “rigid” on the beginning of a dimension at every accuracy and on the end of a dimension at accuracy=2. “rigid” on the end of a dimension with accuracy >= 4, and “free” and “periodic” on any face, raisedeepwave.DeepwaveNotImplementedError: those guard-ring fills do not conserve a discrete energy, so the solution can grow without bound. Model a free surface with a vacuum layer (the improved vacuum method) instead; put a “rigid” face at the beginning of the dimension (flip the model along that axis), or use accuracy=2. Faces may be accepted in a later release; none is removed.pml_freq – See
deepwave.elastic().mpml_fraction – The multiaxial PML (M-PML) cross-damping fraction. See
deepwave.elastic(). Anisotropic media are the primary use case for M-PML: strong anisotropy is a known trigger of C-PML instability, and a small positivempml_fraction(0.15-0.2) cures it at the cost of slightly larger boundary reflections. Default 0.0 (standard C-PML, byte-identical to not having the feature).max_vel – See
deepwave.elastic(), and the note above about the default bound computed from the stiffnesses.courant_number – See
deepwave.elastic().survey_pad – See
deepwave.scalar().vz_0 – See
deepwave.elastic()(and similarly for all the other initial wavefields and PML memory variables).vy_0 – See
deepwave.elastic().vx_0 – See
deepwave.elastic().sigmazz_0 – See
deepwave.elastic().sigmayz_0 – See
deepwave.elastic().sigmaxz_0 – See
deepwave.elastic().sigmayy_0 – See
deepwave.elastic().sigmaxy_0 – See
deepwave.elastic().sigmaxx_0 – See
deepwave.elastic().initial_state – See
deepwave.elastic(). The individual absorbing-boundary field names (m_vzz_0, …, m_sigmaxxx_0) are no longer accepted as keys; pass auxiliary_state instead.origin – See
deepwave.elastic().nt – See
deepwave.elastic().model_gradient_sampling_interval – See
deepwave.elastic().checkpoint_segments –
If given, split the time axis into this many segments and run each of them under
torch.utils.checkpoint, which is the memory lever for a run whose wavefield history does not fit: peak backward memory falls to roughly one segment’s history plus the states held at the segment boundaries, at the cost of running the forward pass of each segment a second time during the backward pass. None (the default) runs the whole time axis in one piece, exactly as before. It is the same thing as callingdeepwave.checkpointing.run_segments()withn_segments=andcheckpoint=True, and returns the same combined output – the same fields, the same info and the same auxiliary_state a direct call gives. initial_state, the storage arguments and every physics option are supported; nt may pad or truncate supplied source amplitudes for the whole run. Source-free nt calls, individual initial-wavefield arguments and per-step callbacks are not supported, and say so.Take the gradient with
loss.backward(). The checkpointing is reentrant, andtorch.utils.checkpointdoes not supporttorch.autograd.grad()(or aninputs=argument to.backward()) in that mode: it raises. If you needtorch.autograd.grad, calldeepwave.checkpointing.run_segments()directly withuse_reentrant=False.freq_taper_frac – See
deepwave.elastic().time_pad_frac – See
deepwave.elastic().time_taper – See
deepwave.elastic().check_output_finite – See
deepwave.elastic().forward_callback – See
deepwave.elastic().backward_callback – See
deepwave.elastic().callback_frequency – See
deepwave.elastic().backend – Which execution backend to use:
"auto"(the default),"compiled","eager"or"torch_compile". See Backends for what each value selects, what"auto"resolves to, and how the backends agree numerically."auto"resolves to the compiled C/CUDA kernel.storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated.
storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated.
storage_compression – Lossy – changes the model gradient by about 0.2-4% in 2-D and 0.2-8% in 3-D. See
deepwave.elastic().location_interpolation – See
deepwave.elastic()."auto"interpolates a floating-point locations Tensor only when at least one non-ignored coordinate lies more thandeepwave.ON_NODE_TOLERANCEcells off its component’s grid node – except that a floating-point Tensor withrequires_grad=Trueis always interpolated, even when every coordinate is on-node, because only the interpolated path carries gradients back to the positions. That changes the forward values for an on-noderequires_gradlocations Tensor relative to the same Tensor withoutrequires_grad. Passlocation_interpolation="none"for the exact path (positions are then not differentiable), or accept the band-limited values.RunInfo.location_interpolation_usedrecords which path was taken:"none"or"hicks", or"mixed"if this propagator has several channels of one kind (several source components, say) and they did not all take the same path.location_interpolation_halfwidth – See
deepwave.elastic().
Elastic VTI Function¶
- deepwave.elastic_vti(c11: Tensor, c13: Tensor, c33: Tensor, c55: Tensor, buoyancy: Tensor, grid_spacing: float | Sequence[float], dt: float, *, c66: Tensor | None = None, sources: Mapping[str, tuple[Tensor, Tensor | Hicks] | tuple[Tensor, Tensor | Hicks, Tensor | None]] | None = None, receivers: Mapping[str, Tensor | Hicks | tuple[Tensor | Hicks, Tensor | None]] | None = None, source_amplitudes_pressure_rate: Tensor | None = None, source_amplitudes_z: Tensor | None = None, source_amplitudes_y: Tensor | None = None, source_amplitudes_x: Tensor | None = None, source_locations_pressure_rate: Tensor | Hicks | None = None, source_locations_z: Tensor | Hicks | None = None, source_locations_y: Tensor | Hicks | None = None, source_locations_x: Tensor | Hicks | None = None, source_mask_pressure_rate: Tensor | None = None, source_mask_z: Tensor | None = None, source_mask_y: Tensor | None = None, source_mask_x: Tensor | None = None, receiver_locations_p: Tensor | Hicks | None = None, receiver_locations_z: Tensor | Hicks | None = None, receiver_locations_y: Tensor | Hicks | None = None, receiver_locations_x: Tensor | Hicks | None = None, receiver_mask_p: Tensor | None = None, receiver_mask_z: Tensor | None = None, receiver_mask_y: Tensor | None = None, receiver_mask_x: Tensor | None = None, vz_0: Tensor | None = None, vy_0: Tensor | None = None, vx_0: Tensor | None = None, sigmazz_0: Tensor | None = None, sigmayz_0: Tensor | None = None, sigmaxz_0: Tensor | None = None, sigmayy_0: Tensor | None = None, sigmaxy_0: Tensor | None = None, sigmaxx_0: Tensor | None = None, initial_state: PropagatorOutput | Mapping[str, Tensor | AuxiliaryState] | None = None, accuracy: Literal[2, 4, 6, 8] = 4, pml_width: int | Sequence[int] = 20, boundary: str | Sequence[str] | None = None, pml_freq: float | None = None, mpml_fraction: float = 0.0, max_vel: float | None = None, courant_number: float | None = None, survey_pad: int | Sequence[int | None] | None = None, origin: Sequence[int] | None = None, nt: int | None = None, model_gradient_sampling_interval: int = 1, checkpoint_segments: int | None = None, freq_taper_frac: float = 0.0, time_pad_frac: float = 0.0, time_taper: bool = False, check_output_finite: bool = True, forward_callback: Callback | None = None, backward_callback: Callback | None = None, callback_frequency: int = 1, backend: str = 'auto', storage: str | Storage | None = None, storage_mode: Literal['device', 'cpu', 'disk', 'none'] | None = None, storage_path: str | PathLike[str] | None = None, storage_compression: bool | None = None, location_interpolation: Literal['auto', 'hicks', 'none'] = 'auto', location_interpolation_halfwidth: int = 4) PropagatorOutput¶
Elastic VTI wave propagation (functional interface).
Stability: experimental (see Stability policy).
This function performs forward modelling with the elastic wave equation in a vertically transverse isotropic (VTI) medium. The outputs are differentiable with respect to the input float torch.Tensors (including every stiffness and the buoyancy).
The propagator uses the same staggered grid, C-PML/M-PML absorbing boundaries, improved-vacuum free surface, source/receiver types, and input/output conventions as
deepwave.elastic(); only the medium description differs. Seedeepwave.elastic()for a full description of the shared arguments and of the returned wavefields and receiver amplitudes. The isotropic propagator is recovered exactly by settingc11 = c33 = lamb + 2 mu,c13 = lamb,c55 = mu(andc66 = muin 3-D).c66is the one model argument whose necessity depends on the dimensionality: it is required in 3-D and must be None in 2-D; every other model is required in both.The symmetry axis of the medium is the slowest spatial dimension:
zin 3-D, andyin a 2-D (P-SV in the (y, x) plane) simulation. There is no 1-D VTI propagator: with a single spatial dimension onlyc33survives in the constitutive relation, which is the isotropic 1-D elastic equation, so 1-D inputs raise an error (usedeepwave.elastic()).All stiffnesses are specified at the normal-stress (integer grid) nodes, with units of pressure (e.g. Pa if working in SI units);
buoyancyis 1/density. The shear stiffnessesc55/c66are internally averaged onto the staggered shear-stress nodes, and the buoyancy onto the staggered velocity nodes, exactly asmuandbuoyancyare in the isotropic propagator (seeprepare_parameters), which also implements the free surface for vacuum cells. In 3-D,c12 = c11 - 2 c66is derived internally. Readable backgrounds are checked for finite values and positive elastic energy: in active cellsc11 > 0,c33 > 0and nonnegative shear stiffnesses are required. The normal block must satisfyc13**2 < c33 * (c11 - c66)in 3-D orc13**2 < c11 * c33in 2-D for positive shear stiffnesses. Supported zero-shear fluid limits permit a semidefinite normal block. Vacuum has zero buoyancy and zero stiffness. See Material models and physical scope for the complete domain and tensor-transform preconditions.When
max_velis omitted, setup chooses a conservative speed bound from the constitutive tensor and staggered density averaging. It accounts for heterogeneous coefficient contrast as well as directional wave speeds; a pointwise phase-speed maximum alone need not bound the discrete operator. An explicitmax_velmust cover this bound. See Discretisation: the exact scheme.Use
deepwave.anisotropy.thomsen_to_cij()to build the stiffnesses from Thomsen parameters; because it is differentiable, inversion may be performed in Thomsen parameter space.Deepwave orders spatial dimensions from slowest-varying to fastest-varying and attaches no physical meaning to any of them; the component suffixes count from the fastest axis, so a 2-D run uses
_yand_xand a 3-D run uses_z,_yand_x. See Dimension order and the axis convention. The one exception to that freedom is this family: its symmetry axis is dimension 0 by construction, so here the axis order is a physics constraint rather than a documentation convention.- Parameters:
c11 – The c11 stiffness model (horizontal P modulus), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c13 – The c13 stiffness model, of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c33 – The c33 stiffness model (vertical P modulus), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c55 – The c55 stiffness model (shear modulus for planes containing the symmetry axis), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.c66 – Required in 3-D; must be None in 2-D (it does not enter the 2-D P-SV equations). The c66 stiffness model (horizontal-plane shear modulus), of shape
[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models. This is the one model whose necessity depends on the number of dimensions.buoyancy – The buoyancy (1/density) model. A cell with
buoyancy = 0is a vacuum, not an infinitely dense cell; see the vacuum sentinel in Boundary conditions, which also explains how the sentinel is averaged onto the staggered nodes. Together with zero stiffnesses it creates a free surface, as indeepwave.elastic(). It is of shape[*model_shape]or, for a batched model,[n_shots, *model_shape], wheremodel_shapehasndimentries. See Batched models.grid_spacing – The spatial grid cell size. It can be a single number that will be used for all dimensions, or a number for each dimension.
dt – The time step interval of the input and output. See
deepwave.elastic()for the unit-consistency requirement (here applying to the stiffnesses,buoyancy,grid_spacing, anddt).source_amplitudes_z – See
deepwave.elastic(). This channel exists only in 3-D.source_amplitudes_y – See
deepwave.elastic().source_amplitudes_x – See
deepwave.elastic().sources – This simulation’s sources, keyed by channel. This is the canonical way to specify a survey. Each value is
(amplitudes, locations), or(amplitudes, locations, mask)to include an activity mask. The channels arepressure_rate,z,y,x(zonly in 3-D); these are equivalent to the flatsource_amplitudes_*/source_locations_*keywords, which remain permanently supported; giving one channel in both forms raises. Optional.receivers – This simulation’s receivers, keyed by channel, as the canonical alternative to the flat
receiver_locations*keywords. Each value is a locations object, or(locations, mask)to include an activity mask. The channels arep,z,y,x(zonly in 3-D). Giving one channel in both forms raises. Optional.source_amplitudes_pressure_rate – See
deepwave.elastic().source_locations_z – See
deepwave.elastic(). This channel exists only in 3-D. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_y – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_x – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_locations_pressure_rate – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it injects nothing. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.source_mask_pressure_rate – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
pressure_ratechannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_pressure_rateare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_pressure_rate, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_z – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_y – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
ychannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.source_mask_x – A boolean torch.Tensor with dimensions [shot, source] selecting which sources of the
xchannel are active.Truemeans active;Falsemeans that point injects nothing, and its coordinates insource_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofsource_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_locations_z – See
deepwave.elastic(). This channel exists only in 3-D. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_y – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_x – See
deepwave.elastic(). A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_locations_p – See
deepwave.elastic(). In 2-D the recorded pressure is the in-plane mean normal stress-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement. A point whose coordinates are alldeepwave.IGNORE_LOCATIONis ignored: it records zeros. A point with only some coordinates set to the sentinel raises. Compare againstdeepwave.IGNORE_LOCATION; do not hard-code its value.receiver_mask_p – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
pchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_pare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_p, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_z – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
zchannel (3-D only) are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_zare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_z, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_y – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
ychannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_yare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_y, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.receiver_mask_x – A boolean torch.Tensor with dimensions [shot, receiver] selecting which receivers of the
xchannel are active.Truemeans active;Falsemeans that point records zeros, and its coordinates inreceiver_locations_xare then ignored entirely (they need not be valid, in range, or unique). The shape must match the leading dimensions ofreceiver_locations_x, which must be given. This is the modern spelling of thedeepwave.IGNORE_LOCATIONsentinel and produces bit-identical results; supplying both a mask and a sentinel-containing locations tensor for the same component raises, as does combining a mask with adeepwave.Hicksobject: aHickscarries its own already-resolved points, so disable points inside it by setting all of their coordinates todeepwave.IGNORE_LOCATIONin the locations it was built from. Optional.accuracy – See
deepwave.elastic(). Default 4.pml_width – See
deepwave.elastic(). Default 20. A face whosepml_widthis zero does not absorb: it becomes an implicit reflecting boundary whose type depends on the propagator and the field component. See Reflecting edges for the per-propagator reflection coefficient and surface location, and prefer naming the condition withboundary(ordeepwave.boundaries()), which also uses the exact image rather than this approximate one.boundary – See
deepwave.elastic(). The same per-field free/rigid/periodic guard-ring image method; the physics/citation reasoning is unchanged by VTI’s stiffness (seedocs/boundaries.rst’s Policy section and_boundaries.py’sfill_elastic_stress_boundary/fill_elastic_velocity_boundarymodule comment). Availability: “pml” is accepted on every face at every accuracy, and “rigid” on the beginning of a dimension at every accuracy and on the end of a dimension at accuracy=2. “rigid” on the end of a dimension with accuracy >= 4, and “free” and “periodic” on any face, raisedeepwave.DeepwaveNotImplementedError: those guard-ring fills do not conserve a discrete energy, so the solution can grow without bound. Model a free surface with a vacuum layer (the improved vacuum method) instead; put a “rigid” face at the beginning of the dimension (flip the model along that axis), or use accuracy=2. Faces may be accepted in a later release; none is removed.pml_freq – See
deepwave.elastic().mpml_fraction – The multiaxial PML (M-PML) cross-damping fraction. See
deepwave.elastic(). Anisotropic media are the primary use case for M-PML: strong anisotropy is a known trigger of C-PML instability, and a small positivempml_fraction(0.15-0.2) cures it at the cost of slightly larger boundary reflections. Default 0.0 (standard C-PML, byte-identical to not having the feature).max_vel – See
deepwave.elastic(), and the note above about the default bound computed from the stiffnesses.courant_number – See
deepwave.elastic().survey_pad – See
deepwave.scalar().vz_0 – See
deepwave.elastic()(and similarly for all the other initial wavefields and PML memory variables).vy_0 – See
deepwave.elastic().vx_0 – See
deepwave.elastic().sigmazz_0 – See
deepwave.elastic().sigmayz_0 – See
deepwave.elastic().sigmaxz_0 – See
deepwave.elastic().sigmayy_0 – See
deepwave.elastic().sigmaxy_0 – See
deepwave.elastic().sigmaxx_0 – See
deepwave.elastic().initial_state – See
deepwave.elastic(). The individual absorbing-boundary field names (m_vzz_0, …, m_sigmaxxx_0) are no longer accepted as keys; pass auxiliary_state instead.origin – See
deepwave.elastic().nt – See
deepwave.elastic().model_gradient_sampling_interval – See
deepwave.elastic().checkpoint_segments –
If given, split the time axis into this many segments and run each of them under
torch.utils.checkpoint, which is the memory lever for a run whose wavefield history does not fit: peak backward memory falls to roughly one segment’s history plus the states held at the segment boundaries, at the cost of running the forward pass of each segment a second time during the backward pass. None (the default) runs the whole time axis in one piece, exactly as before. It is the same thing as callingdeepwave.checkpointing.run_segments()withn_segments=andcheckpoint=True, and returns the same combined output – the same fields, the same info and the same auxiliary_state a direct call gives. initial_state, the storage arguments and every physics option are supported; nt may pad or truncate supplied source amplitudes for the whole run. Source-free nt calls, individual initial-wavefield arguments and per-step callbacks are not supported, and say so.Take the gradient with
loss.backward(). The checkpointing is reentrant, andtorch.utils.checkpointdoes not supporttorch.autograd.grad()(or aninputs=argument to.backward()) in that mode: it raises. If you needtorch.autograd.grad, calldeepwave.checkpointing.run_segments()directly withuse_reentrant=False.freq_taper_frac – See
deepwave.elastic().time_pad_frac – See
deepwave.elastic().time_taper – See
deepwave.elastic().check_output_finite – See
deepwave.elastic().forward_callback – See
deepwave.elastic().backward_callback – See
deepwave.elastic().callback_frequency – See
deepwave.elastic().backend – Which execution backend to use:
"auto"(the default),"compiled","eager"or"torch_compile". See Backends for what each value selects, what"auto"resolves to, and how the backends agree numerically."auto"resolves to the compiled C/CUDA kernel.storage – The storage policy for the wavefield history that the model gradient is computed from, as one object: either a mode string (“device”, “cpu”, “disk” or “none”) or a
deepwave.Storage, which also carries the path and the lossy-compression flag. Defaults to “device”. This is an alternative spelling for the four individual storage_* arguments below, which remain permanently supported and are not deprecated; passing storage together with any of them raises DeepwaveValueError, because there is no honest way to merge two policies.storage_mode – A string specifying the storage mode for intermediate data. One of “device”, “cpu”, “disk”, or “none”. Defaults to “device”. A permanent alias for Storage.mode; not deprecated.
storage_path – The directory that storage_mode=”disk” writes to. A string or any os.PathLike (such as a pathlib.Path). Defaults to the system temporary directory, resolved when you call rather than when Deepwave is imported, so TMPDIR set at any point before the call is honoured. Using the default with storage_mode=”disk” emits a one-time warning naming the directory, because on many systems it is a RAM-backed tmpfs far smaller than the disk. A permanent alias for Storage.path; not deprecated.
storage_compression – Lossy – changes the model gradient by about 0.2-4% in 2-D and 0.2-8% in 3-D. See
deepwave.elastic().location_interpolation – See
deepwave.elastic()."auto"interpolates a floating-point locations Tensor only when at least one non-ignored coordinate lies more thandeepwave.ON_NODE_TOLERANCEcells off its component’s grid node – except that a floating-point Tensor withrequires_grad=Trueis always interpolated, even when every coordinate is on-node, because only the interpolated path carries gradients back to the positions. That changes the forward values for an on-noderequires_gradlocations Tensor relative to the same Tensor withoutrequires_grad. Passlocation_interpolation="none"for the exact path (positions are then not differentiable), or accept the band-limited values.RunInfo.location_interpolation_usedrecords which path was taken:"none"or"hicks", or"mixed"if this propagator has several channels of one kind (several source components, say) and they did not all take the same path.location_interpolation_halfwidth – See
deepwave.elastic().
- Returns:
a tuple subclass whose fields, in order, are the same names as
deepwave.elastic()’s Returns (velocities, then stresses, each grouped by kind and ordered slowest-to-fastest dimension, then the auxiliary state, followed by the receiver amplitudes: pressure, then the velocity components):vz_0: Final velocity wavefield in the z-dimension (if ndim == 3).
vy_0: Final velocity wavefield in the y-dimension.
vx_0: Final velocity wavefield in the x-dimension.
sigmazz_0: Final stress wavefield (zz component) (if ndim == 3).
sigmayz_0: Final stress wavefield (yz component) (if ndim == 3).
sigmaxz_0: Final stress wavefield (xz component) (if ndim == 3).
sigmayy_0: Final stress wavefield (yy component).
sigmaxy_0: Final stress wavefield (xy component).
sigmaxx_0: Final stress wavefield (xx component).
auxiliary_state: A
deepwave.AuxiliaryStateholding the absorbing boundary’s memory variables. Opaque: pass it back (as part of initial_state) to continue the simulation; its contents are implementation state rather than physics.receiver_amplitudes_p: Recorded pressure data. In 2-D the recorded pressure is the in-plane mean normal stress
-(sigma_xx + sigma_yy)/2, which under plane strain is not the thermodynamic pressure; seedeepwave.elastic()’sreceiver_amplitudes_pentry for the full statement.receiver_amplitudes_z: Recorded z-component velocity data (if ndim == 3).
receiver_amplitudes_y: Recorded y-component velocity data.
receiver_amplitudes_x: Recorded x-component velocity data.
This positional order is easy to index incorrectly (
out[-1]is the x-component velocity receiver amplitudes, not the pressure data); prefer accessing the fields by name instead.- Return type: