This page here has been created for the latest stable release of Salvus. You have chosen to view the documentation for another Salvus version. Please be aware there might be some small differences you have to account for.
QKAPPA
as a material
parameter.SegyEvent
, but it should be straightforward to
upgrade.paramiko.SSHClient.connect()
to allow more fine tuning for some SSH connections.[sites.my_site.ssh_settings] hostname = "some_host" username = "some_user" [sites.my_site.ssh_settings.extra_paramiko_connect_arguments.disabled_algorithms] pubkeys = ["rsa-sha2-512", "rsa2-sha2-256"]
init-site
command now has a --verbose
flag to facilitate
debugging tricky connections:salvus-cli init-site my_site --verbose
mpirun_template
parameter for ssh
and local
site types that allows
full customization of the actual call to mpirun
in case it is necessary.[sites.my_site.site_specific] mpirun_template = "/custom/mpirun -machinefile ~/mf -n {RANKS}"
mpirun
executable with a non-standard
argument for all Salvus runs on that site. The {RANKS}
argument will be
filled in by Salvus with the number of ranks for each simulation.UnstructuredMeshSimulationConfiguration
objects are now properly recognized when trying to overwrite an existing
configuration of the same name.StructuredModel
to SalvusOpt to invert models
parameterized on a regular grid using xarray.Datasets.WaveformSimulationConfiguration
.Stats
tab of the iteration widget.WaveformSimulationConfiguration
. This is useful for Dirichlet-type
boundaries or absorbing boundaries of a
UnstructuredMeshSimulationConfiguration
.
Boundaries specified here will be applied in addition to ocean load and/or
absorbing boundaries specified as AbsorbingBoundaryParameters
in the
SimulationConfiguration
. A ValueError
is raised for duplicated conditions
on a side set.compute_misfits
, the simulation results are
considered corrupted and will be automatically deleted. This means that those
simulations will be resubmitted when calling compute_misfits
again.TaskChain
.StructuredGrid2D
, StructuredGrid3D
and Skeleton
classes and
replaced them with new MeshBlock
and MeshBlockCollection
classes.iterate()
and resume()
. Specifying site_name
,
ranks_per_job
and wall_time_in_seconds_per_job
is no longer
supported. Instead, the job_submission_settings
either need to be passed to
the constructor of the InverseProblemConfiguration
or by using
p.inversions.set_job_submission_configuration()
.p.simulations.query( simulation_configuration="my_simulation", misfit_configuration="my_misfit", wavefield_compression=sn.WavefieldCompression( forward_wavefield_sampling_interval=15 ), events=p.events.list(), )
wget https://mondaic.com/environment.yml -O ~/environment.yml conda env update -n salvus -f ~/environment.yml
TaskChain
workflow primitive that can be used to run multiple Salvus jobs
and/or Python scripts in a linear chain within a single local/ssh/HPC job.# Construct a forward simulation object. w_forward = sn.simple_config.simulation.Waveform( ..., store_adjoint_checkpoints=True ) # Construct an adjoint simulation object. w_adjoint = sn.simple_config.simulation.Waveform(...) ... # There is a new `PROMISE_FILE:` prefix to tell SalvusFlow that a file does # not exist yet but it will exist when the simulation is run. w_adjoint.adjoint.point_source_block = { "filename": "PROMISE_FILE:task_2_of_2/input/adjoint_source.h5", "groups": ["adjoint_sources"], } # Define a Python function that is run between forward and adjoint simulations # to generate the adjoint sources. def compute_adjoint_source( task_index: int, task_index_folder_map: typing.Dict[int, pathlib.Path] ): folder_forward = task_index_folder_map[task_index - 1] folder_adjoint = task_index_folder_map[task_index + 1] output_folder = folder_forward / "output" event = sn.EventData.from_output_folder(output_folder=output_folder) event_misfit = sn.EventMisfit( synthetic_event=event, misfit_function="L2_energy_no_observed_data", receiver_field="displacement", ) input_folder_adjoint = folder_adjoint / "input" event_misfit.write(input_folder_adjoint / "adjoint_source.h5") # Launch the task chain. It will serialize the Python function and launches # everything either locally or in Slurm/other supported systems. tc = sn.api.run_task_chain_async( site_name="local", tasks=[w_forward, compute_adjoint_source, w_adjoint], ranks=4, ) # Wait until it finishes. tc.wait()
mesh = p.simulations.get_mesh("sim") # Modify scaling parameters for all fields mesh.elemental_fields["VP"] = ... mesh.elemental_fields["RHO"] = ... m = Mapping( scaling=mesh, inversion_parameters=["M"], map_to_physical_parameters={"VP": "M", "RHO": "M"}, )
model.background.one_dimensional.FromBm
.sn.WavefieldCompression( forward_wavefield_sampling_interval=N )
N
during the
adjoint run.
forward_wavefield_sampling_interval=1
corresponds to no compression and is
equivalent to what was done prior to this release.forward_wavefield_sampling_interval=1
,
which is consistent with Salvus <= 0.11.47
.# Inversion actions: p.action.inversion.compute_misfits( ..., derived_job_config=sn.WavefieldCompression( forward_wavefield_sampling_interval=5 ), ... ) p.action.inversion.compute_gradients( ..., wavefield_compression=sn.WavefieldCompression( forward_wavefield_sampling_interval=5 ), ... ) p.action.inversion.sum_gradients( ..., wavefield_compression=sn.WavefieldCompression( forward_wavefield_sampling_interval=5 ), ... ) # InverseProblemConfiguration sn.InverseProblemConfiguration( ... wavefield_compression=sn.WavefieldCompression( forward_wavefield_sampling_interval=5 ), ... )
store_adjoint_checkpoints
in p.simulations.launch(...)
and
store_checkpoints
in p.actions.inversion.compute_misfits(...)
are
deprecated. Instead, usederived_job_config=WavefieldCompression( forward_wavefield_sampling_interval=N ),
derived_job_config=None
is the new default, which corresponds
to the deprecated store_adjoint_checkpoints=False
or
store_checkpoints=False
, respectively.compute_misfits
and compute_gradients
in p.action.inversion
are now
keyword-only functions. Additionally, we made the wavefield compression
settings mandatory arguments of a few lower-level functions, such as:p.misfits.get_gradient_filenames() p.simulations.get_adjoint_input_files() p.action.validation.validate_model_gradients()
TypeError: compute_gradients() needs keyword-only argument wavefield_compression
UnstructuredMeshSimulationConfiguration
.[[sites.site_name.site_specific.additional_qsub_arguments]] name = "pe" value = "mpi {NODES * TASKS_PER_NODE}" [[sites.site_name.site_specific.additional_qsub_arguments]] name = "l" value = "ngpus={int(ceil(RANKS / 12))}"
lat_lng_to_utm_crs()
helper routine to directly get a pyproj UTM
CRS object from a point given in latitude and longitude.salvus-cli
alias for the salvus-flow
command line call. This will
become the default at one point.p.misfits.compute_adjoint_source()
EventWindowAndWeightSet
in case
the window selection routine did not pick a single window for a chosen event.p.actions.seismology.get_events_with_windows("DSC_NAME")
UTMDomain
objects no longer require the ellipsoid to be passed.salvus-flow upgrade
and salvus-flow upgrade-site
for
double precision versions using the salvus_f64
binary.init-site
script will wait a bit longer for the stderr
in case it is
not yet available due to some synchronization delays on shared and parallel
file systems.UnstructuredMesh.extrude_side_set_2D()
method now also works as expected
for higher order meshes. Additionally fixed an issue with inverted elements
in certain scenarios.InverseProblemConfiguration
after
the project has been transferred to another python environment with a
different site configuration.Event( event_name="event", sources=[point_src1, point_src2], receivers=receivers, ) ... EventConfiguration( waveform_simulation_configuration=..., wavelet=[ simple_config.stf.Ricker(center_frequency=1.0), simple_config.stf.Ricker(center_frequency=2.0), ], )
int
instead of float
types.p.viz.shotgather( data="simulation", event="event", receiver_field="phi", component="A" )
extra_output_configuration
to the launch function.p.simulations.launch( ranks_per_job=4, site_name="local", events=p.events.list(), simulation_configuration="simulation", extra_output_configuration={ "frequency_domain": { "fields": ["displacement"], "frequencies": [1.0, 2.0, 3.0], } }, )
event_misfit = EventMisfit( ..., # Optionally downsample to the given number of npts. max_samples_for_misfit_computation=max_samples_for_misfit_computation )
mc = MisfitConfiguration( ..., # Optionally downsample to the given number of npts. max_samples_for_misfit_computation=max_samples_for_misfit_computation
from salvus.modules.near_surface.processing import convert_point_to_line_source new_st = convert_point_to_line_source( st=st, source_coordinates=[22.0, 1.0], receiver_coordinates=[132.0, 0.0], transform_type="single_velocity_exact", velocity_m_s=550.0 )
import numpy as np from salvus.modules.near_surface.processing import geophone_response frequencies = np.logspace(0.1, 2, 2000) response = geophone_response.compute_geophone_response( frequencies=frequencies, geophone_frequency=4.5, damping_ratio=0.4, calibration_factor=11.2, ) geophone_response.plot_response(frequencies=frequencies, response=response)
L. Métivier, R. Brossier, Q. Mérigot, and E. Oudet. 2019."A graph space optimal transport distance as a generalization of Lp  distances: application to a seismic imaging inverse problem"Inverse Problems, Volume 35, Number 8, https://doi.org/10.1088/1361-6420/ab206f
"graph_space_optimal_tranport"
everywhere Salvus
accepts misfit functionals. The one tuning parameters is the
"max_expected_time_shift"
which, as the name implies, should be set to the
maximum expected time shift in seconds for individual wiggles between observed
and synthetic data."EXTERNAL_DATA:raw_data | bandpass(1.0, 2.0) | normalize"
as the data name.time_shift({SHIFT})
normalize
scale({FACTOR})
flip
bandpass({FREQ_MIN}, {FREQ_MAX}[, zerophase][, corners={CORNERS}])
p.viz.shotgather( data=[ "PROCESSED_DATA:corrected_data_10_15_hz | normalize", "SYNTHETIC_DATA:starting_model_10_15_hz | normalize", ], event="shot_049", receiver_field="velocity", component="Y", sort_by=lambda r: r.location[0] )
mesh_from_xarray
function in the Salvus Toolbox. This allows one to override the default spline
interpolation routine, which may be useful in the presence of strong velocity
contrasts.simple_config.Waveform
objects by lazy evaluation of
UnstructuredMesh objects.p.inversions.delete_disposable_files( inverse_problem_configuration="my_inversion", data_to_remove=["auxiliary", "waveforms", "gradients"] )
auxiliary
, waveforms
, gradients
, because gradients are the most
expensive to recompute.# Delete waveforms p.simulations.delete_results( simulation_configuration="my_sim_config", events=["event"] ) # Delete gradients p.simulations.delete_results( simulation_configuration="my_sim_config", misfit_configuration="my_misfit_config", events=p.events.list() )
mesh = basic_mesh.CartesianHomogeneousAcoustic2D( vp=1500.0, rho=1000.0, x_max=1.0, y_max=0.5, max_frequency=1e3, ).create_mesh() mesh = mesh.extrude_side_set_2D( side_set="x1", offsets=np.array([0.0, 2.0, 4.0]), direction="x", )
-np.infty
to deform all elements in y
direction
with negative y
coordinates.mesh = basic_mesh.CartesianHomogeneousAcoustic2D( vp=1500.0, rho=1000.0, x_max=1.0, y_max=2.0, max_frequency=10e3 ).create_mesh() mesh.points[:, 1] -= 0.5 mesh.add_dem_2D( x=np.array([0.0, 1.0]), dem=np.array([-0.25, 0.25]), y0=-np.infty, y1=np.infty, kx=1, ky=1, ) mesh.apply_dem()
hdf5-full
and hdf5-minimal
.
hdf5-full
contains additional fields stored in the input mesh, e.g., the
index of layers / regions. hdf5-minimal
will only write the data fields of
the gradient, but neither coordinates, connectivity nor an xdmf file.hdf5
remains unchanged..to_list()
function to all receiver collections so that multiple
collections can more easily be appended to each other.free_surface
argument of
AbsorbingBoundaryParameters
. These side sets will in turn not be extended with
absorbing layers (if they are requested), and no absorbing conditions will be
placed on them. This is useful, for instance, to model a thing plate
(free_surface=["z0", "z1"]
).mesh = p.simulations.get_mesh("initial_model") lb = mesh.copy() lb.elemental_fields["VP"] *= 0.8 lb.elemental_fields["RHO"] *= 0.8 ub = mesh.copy() ub.elemental_fields["VP"] *= 1.2 ub.elemental_fields["RHO"] *= 1.2 p.inversions.set_constraints( inverse_problem_configuration="my_third_inversion", constraints={ "lower_bounds": lb, "upper_bounds": ub, }, )
xarray
and SQLAlchemy
. A consequence of this is that the Python netCDF4
package is now a hard dependency.xarray
and SQLAlchemy
.
The netCDF4
package is now a hard dependency which should improve
compatibility when reading and writing files with xarray
.salvus-flow add-site
wizard will now also ask if it should
run Salvus using GPUs on a newly configured site.SiteNameValidator
that caused add-site
to crash when no other site has been initialized yet.unstructured_mesh_utils._match_layers
that could
crop up if a mesh was generated outside of SalvusProject.get_enclosing_elements
would
not return the proper reference coordinates.salvus.mesh.tools.transforms
. Along with full-mesh interpolations,
layer-to-layer discontinuity-preserving interpolations, and "flattened"
interpolations handling topographic deformations, are supported. Additional
helper functions for re-meshing applications have also been added to
salvus.mesh.unstructured_mesh_utils
. One of theses is a function to extract
a conservative 1-D model from an unstructured mesh, which helps to ensure that
a new mesh can be generated that respects both the 3-D minimum velocities and
existing discontinuities. Another is a function to match up layers between
two unstructured meshes in the case that their IDs are different. This is
helpful in the case where the interpolation should respect pre-defined
discontinuities in the model.simple_config.simulation.Waveform
object using
output.frequency_domain
.SphericalChunkDomain
together with a spherical polygon to further constrain
the spatial extent. Most importantly conversions between WGS84 and fully
spherical coordinates are now consistent with the rest of Salvus. The
in-notebook domain plot now also works and shows the original spherical chunk
together with the domain polygon.