This documentation is not for the latest stable Salvus version.
import os
import numpy as np
import xarray as xr
import salvus.namespace as sn
SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")
# Generate a ring with 5 scalar sources.
sources = sn.simple_config.source.cartesian.collections.ScalarPoint2DRing(
x=0, y=0, radius=0.09, count=5, f=1.0
)
events = []
# Use the same receiver ring for each but mask out the receivers close to each
# source.
for i, s in enumerate(sources._sources):
all_receivers = (
sn.simple_config.receiver.cartesian.collections.RingPoint2D(
x=0, y=0, radius=0.09, count=100, fields=["phi"]
)
)
receivers = [
r
for r in all_receivers._receivers
if np.sqrt(
(s.location[0] - r.location[0]) ** 2
+ (s.location[1] - r.location[1]) ** 2
)
> 0.03
]
events.append(
sn.Event(event_name=f"event_{i}", sources=s, receivers=receivers)
)
def get_spherical_inclusion() -> xr.Dataset:
nx, ny = 200, 200
x = np.linspace(-0.1, +0.1, nx)
y = np.linspace(-0.1, +0.1, ny)
xx, yy = np.meshgrid(x, y, indexing="ij")
# Add 3 spherical inclusions
vp = 1500.0 * np.ones_like(xx)
rho = 980.0 * np.ones_like(xx)
mask = np.sqrt(xx**2 + yy**2) < 0.05
vp[mask] = 1480.0
rho[mask] = 1000.0
mask = np.sqrt(xx**2 + (yy - 0.025) ** 2) < 0.015
vp[mask] = 1550.0
rho[mask] = 1040.0
mask = np.sqrt(xx**2 + (yy + 0.025) ** 2) < 0.015
vp[mask] = 1460.0
rho[mask] = 1010.0
ds = xr.Dataset(
data_vars={
"vp": (["x", "y"], vp),
"rho": (["x", "y"], rho),
},
coords={"x": x, "y": y},
)
return ds
true_model = get_spherical_inclusion()
ax = true_model.vp.T.plot(figsize=(10, 6))
ax.axes.set_aspect("equal")
# Use the volume model to set up the project.
volume_model = sn.model.volume.cartesian.GenericModel(
name="true_model", data=true_model
)
p = sn.Project.from_volume_model(
path="project_full_waveform_inversion",
volume_model=volume_model,
load_if_exists=True,
)
# Add the events.
for event in events:
p.add_to_project(event)
p.visualizations.notebook.domain()
# Generate the data for the target model.
wsc = sn.WaveformSimulationConfiguration(end_time_in_seconds=0.00015)
wsc.physics.wave_equation.time_step_in_seconds = 4.0e-7
ec = sn.EventConfiguration(
waveform_simulation_configuration=wsc,
wavelet=sn.simple_config.stf.Ricker(center_frequency=50000.0),
)
p += sn.SimulationConfiguration(
name="true_model_100kHz",
elements_per_wavelength=2,
tensor_order=4,
max_frequency_in_hertz=100000.0,
model_configuration=sn.ModelConfiguration(
background_model=None, volume_models="true_model"
),
event_configuration=ec,
)
p.simulations.launch(
simulation_configuration="true_model_100kHz",
events=p.events.list(),
site_name=SALVUS_FLOW_SITE_NAME,
ranks_per_job=1,
)
p.simulations.query(block=True)
[2025-04-15 19:24:39,221] INFO: Creating mesh. Hang on. [2025-04-15 19:24:39,335] INFO: Submitting job array with 5 jobs ...
True
bm = sn.model.background.homogeneous.IsotropicAcoustic(vp=1500.0, rho=980.0)
mc = sn.ModelConfiguration(background_model=bm)
wsc = sn.WaveformSimulationConfiguration(end_time_in_seconds=0.00015)
p += sn.SimulationConfiguration(
name="initial_model",
elements_per_wavelength=2,
tensor_order=2,
max_frequency_in_hertz=100000.0,
model_configuration=mc,
event_configuration=sn.EventConfiguration(
waveform_simulation_configuration=wsc,
wavelet=sn.simple_config.stf.Ricker(center_frequency=50000.0),
),
)
p.simulations.launch(
simulation_configuration="initial_model",
events=p.events.list(),
site_name=SALVUS_FLOW_SITE_NAME,
ranks_per_job=1,
)
p.simulations.query(block=True)
[2025-04-15 19:24:46,800] INFO: Creating mesh. Hang on. [2025-04-15 19:24:46,863] INFO: Submitting job array with 5 jobs ...
True
# The misfit configuration defines how synthetics are compared to observed data.
p += sn.MisfitConfiguration(
name="L2",
# Could be observed data. Here we compare to the synthetic target.
observed_data="true_model_100kHz",
# Salvus comes with a variety of misfit functions. You can
# also define your own.
misfit_function="L2",
# This is an acoustic simulation so we'll use recordings of phi.
receiver_field="phi",
)
# Now we define the actual inverse problem
p += sn.InverseProblemConfiguration(
name="my_inversion",
# Starting model.
prior_model="initial_model",
# The events to use.
events=p.events.list(),
# What parameters to invert for.
mapping=sn.Mapping(scaling="absolute", inversion_parameters=["VP", "RHO"]),
# The smoothing.
preconditioner=sn.ConstantSmoothing({"VP": 0.01, "RHO": 0.01}),
# The inversion method.
method=sn.TrustRegion(initial_trust_region_linf=10.0),
# The misfit configuration we defined above.
misfit_configuration="L2",
# Compress the forward wavefield by subsampling in time.
wavefield_compression=sn.WavefieldCompression(
forward_wavefield_sampling_interval=10
),
# Job submission settings.
job_submission=sn.SiteConfig(
site_name=SALVUS_FLOW_SITE_NAME, ranks_per_job=1
),
)
# Lastly we perform two iterations, and have a look at the results.
for i in range(2):
p.inversions.iterate(
inverse_problem_configuration="my_inversion",
timeout_in_seconds=360,
ping_interval_in_seconds=2,
delete_disposable_files="all",
)
[2025-04-15 19:24:53,496] INFO: Adding new iteration #0. [2025-04-15 19:24:53,504] INFO: Resuming iteration #0. [2025-04-15 19:24:53,509] INFO: 1 new tasks have been issued. [2025-04-15 19:24:53,510] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:24:53,588] INFO: The following events have been simulated before, but checkpoints are not available for this combination of `site_name` and `ranks_per_job` and wavefield compression settings. They will be run again: ['event_0', 'event_1', 'event_2', 'event_3', 'event_4'] [2025-04-15 19:24:53,613] INFO: Submitting job array with 5 jobs ... [2025-04-15 19:24:53,984] INFO: Launched simulations for 5 events. Please check again to see if they are finished. [2025-04-15 19:24:53,985] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:24:55,986] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:24:56,113] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:24:58,115] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:24:58,212] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:00,214] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:25:01,977] INFO: Submitting job array with 5 jobs ...
Uploading 1 files... Uploading 1 files... Uploading 1 files... Uploading 1 files... Uploading 1 files... [2025-04-15 19:25:02,036] INFO: Launched adjoint simulations for 5 events. Please check again to see if they are finished. [2025-04-15 19:25:02,037] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:04,039] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:25:04,330] INFO: 5 events have already been submitted. They will not be submitted again. [2025-04-15 19:25:04,416] INFO: Some simulations are still running. Please check again to see if they are finished. [2025-04-15 19:25:04,418] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:06,420] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:25:06,660] INFO: 5 events have already been submitted. They will not be submitted again. [2025-04-15 19:25:06,725] INFO: Some simulations are still running. Please check again to see if they are finished. [2025-04-15 19:25:06,726] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:08,727] INFO: Processing task `misfit_and_gradient` [2025-04-15 19:25:09,165] INFO: 5 events have already been submitted. They will not be submitted again. [2025-04-15 19:25:09,565] INFO: Iteration 0: Number of events: 5 chi = 0.01769007842184961 ||g|| = 0.022565013801719613 pred = --- ared = --- norm_update = --- tr_radius = --- [2025-04-15 19:25:09,567] INFO: 1 new tasks have been issued. [2025-04-15 19:25:09,567] INFO: Processing task `preconditioner` [2025-04-15 19:25:09,637] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:11,647] INFO: Processing task `preconditioner` [2025-04-15 19:25:11,771] INFO: 1 new tasks have been issued. [2025-04-15 19:25:11,772] INFO: Processing task `misfit` [2025-04-15 19:25:11,824] INFO: Submitting job array with 5 jobs ... [2025-04-15 19:25:11,940] INFO: Launched simulations for 5 events. Please check again to see if they are finished. [2025-04-15 19:25:11,941] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:13,970] INFO: Processing task `misfit` [2025-04-15 19:25:14,030] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:16,058] INFO: Processing task `misfit` [2025-04-15 19:25:16,124] INFO: Some tasks of iteration #0 are still running. Please check again later. [2025-04-15 19:25:18,152] INFO: Processing task `misfit` [2025-04-15 19:25:20,794] INFO: old misfit control group: 0.01769007842184961 new misfit control group: 0.006215538423932317 predicted reduction control group: -0.009679727771306901 actual reduction control group: -0.011474539997917293 5 out of 5 event(s) improved the misfit. [2025-04-15 19:25:20,794] INFO: Model update accepted. [2025-04-15 19:25:20,795] INFO: 1 new tasks have been issued. [2025-04-15 19:25:20,796] INFO: Processing task `finalize_iteration` [2025-04-15 19:25:20,919] INFO: ... searching for obsolete files in project_full_waveform_inversion/INVERSIONS/my_inversion/00000 [2025-04-15 19:25:20,944] INFO: Freed up 1.2 MB of space. [2025-04-15 19:25:20,964] INFO: Succesfully completed iteration #0. [2025-04-15 19:25:20,966] INFO: Adding new iteration #1. [2025-04-15 19:25:20,981] INFO: Resuming iteration #1. [2025-04-15 19:25:20,981] INFO: 1 new tasks have been issued. [2025-04-15 19:25:20,982] INFO: Processing task `gradient` [2025-04-15 19:25:21,436] INFO: Submitting job array with 5 jobs ...
Uploading 1 files... Uploading 1 files... Uploading 1 files... Uploading 1 files... Uploading 1 files... [2025-04-15 19:25:21,715] INFO: Launched adjoint simulations for 5 events. Please check again to see if they are finished. [2025-04-15 19:25:21,722] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:23,733] INFO: Processing task `gradient` [2025-04-15 19:25:24,068] INFO: 5 events have already been submitted. They will not be submitted again. [2025-04-15 19:25:24,295] INFO: Some simulations are still running. Please check again to see if they are finished. [2025-04-15 19:25:24,297] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:26,310] INFO: Processing task `gradient` [2025-04-15 19:25:26,647] INFO: 5 events have already been submitted. They will not be submitted again. [2025-04-15 19:25:26,793] INFO: Some simulations are still running. Please check again to see if they are finished. [2025-04-15 19:25:26,803] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:28,809] INFO: Processing task `gradient` [2025-04-15 19:25:29,458] INFO: 5 events have already been submitted. They will not be submitted again. [2025-04-15 19:25:30,186] INFO: Iteration 1: Number of events: 5 chi = 0.006215538423932317 ||g|| = 0.009661533661238208 pred = -0.009679727771306901 ared = -0.011474539997917293 norm_update = 0.9534161427441019 tr_radius = 0.9534163618503646 [2025-04-15 19:25:30,203] INFO: 1 new tasks have been issued. [2025-04-15 19:25:30,204] INFO: Processing task `preconditioner` [2025-04-15 19:25:30,385] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:32,477] INFO: Processing task `preconditioner` [2025-04-15 19:25:32,623] INFO: 1 new tasks have been issued. [2025-04-15 19:25:32,624] INFO: Processing task `misfit` [2025-04-15 19:25:32,674] INFO: Submitting job array with 5 jobs ... [2025-04-15 19:25:32,777] INFO: Launched simulations for 5 events. Please check again to see if they are finished. [2025-04-15 19:25:32,778] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:34,816] INFO: Processing task `misfit` [2025-04-15 19:25:34,870] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:36,911] INFO: Processing task `misfit` [2025-04-15 19:25:36,968] INFO: Some tasks of iteration #1 are still running. Please check again later. [2025-04-15 19:25:39,006] INFO: Processing task `misfit` [2025-04-15 19:25:41,253] INFO: old misfit control group: 0.006215538423932317 new misfit control group: 0.004515146195660988 predicted reduction control group: -0.0008915795911773164 actual reduction control group: -0.0017003922282713291 5 out of 5 event(s) improved the misfit. [2025-04-15 19:25:41,254] INFO: Model update accepted. [2025-04-15 19:25:41,254] INFO: 1 new tasks have been issued. [2025-04-15 19:25:41,255] INFO: Processing task `finalize_iteration` [2025-04-15 19:25:41,368] INFO: ... searching for obsolete files in project_full_waveform_inversion/INVERSIONS/my_inversion/00001 [2025-04-15 19:25:41,567] INFO: Freed up 4.8 MB of space. [2025-04-15 19:25:41,568] INFO: Succesfully completed iteration #1. [2025-04-15 19:25:41,570] INFO: Adding new iteration #2.
p.viz.nb.inversion(inverse_problem_configuration="my_inversion")