Salvus 2024.1.1
This is the first minor update to the 2024.1 release.
Notable changes include the handling of material parameterizations in Salvus and a new way of parallelism for simulations on shared filesystems (e.g. local sites or workstations). We have also made it a lot easier to add external data to a project.
Changes
Updated the Salvus Jupyter notebook snippets collection now works with Jupyter notebooks >= 7 as well as JupyterLab.
%load_ext salvus
%salvus_snippetsAdded new functionality to facilitate adding external data
to a Salvus project per event. The function
salvus.data.external_data_to_hdf5 takes an
xarray.Dataset, validates it, and converts it to a Salvus
compatible HDF5 file, which can be added to a project.
from salvus.data import external_data_to_hdf5
for event in project.events.list():
external_data_to_hdf5(
data=data_per_event,
receivers=event.receivers,
receiver_field="displacement",
output_filename=external_data_path,
)
project.waveforms.add_external(
data_name="observed_data",
event=event.event_name,
data_filename=external_data_path,
)
The internal BM file writer in SalvusMesh previously did not check for invalid
interface definitions, and may have written BM files which contain a
triplication (or greater) of coordinate / value pairs at an interface. This has
now been remedied, and BM files generated via get_bm_string should now contain
only duplicated pairs at most. This issue may have affected those generating
background models in SalvusProject from an n-dimensional xarray dataset.
The material submodule of the layered_mesher has been promoted to a
full-fledged top level module for Salvus. Although it is still available as an
alias in the layered mesher submodule of salvus.mesh (i.e.
salvus.mesh.layered_mesher.material), accessing it this way is not
encouraged.
Added the option to pass materials to background models, per the following method:
# Acoustic isotropic material
material_sandstone = material.acoustic.Velocity.from_params(
rho=1500, vp=1875
)
# Or something more exotic
material_weird_sandstone = material.elastic.triclinic.TensorComponents(
...
)
mc_sandstone = sn.ModelConfiguration(
background_model=sn.model.background.homogeneous.FromMaterial(
material=material_sandstone
)
)
sc_sandstone = sn.SimulationConfiguration(
name="sandstone",
model_configuration=mc_sandstone,
...
)
Only supports homogeneous and not location-dependent materials.
Added find_side_sets_enclosing as a method to meshes to find a all side sets
that enclose the mesh, by first finding all planar surfaces and constructing
the remainder surface from all unclaimed facets.
Fix a bug where the ocean layer would not be positioned correctly in cartesian domains with strict top and bottom domain boundaries.
Salvus now supports custom data normalization functions for use in misfit computations and inverse problems.
def forward_norm(data_synthetic, data_observed, sampling_rate_in_hertz):
...
def jacobian_norm(
adjoint_source, data_synthetic, data_observed, sampling_rate_in_hertz
):
...
norm = sn.TraceNormalization(forward=forward_norm, jacobian=jacobian_norm)
p += sn.MisfitConfiguration(
...,
normalization=norm,
)Added optional events as a setting to p.viz.nb’s misfits, to visualize
misfits only for selected events. If not passed, to previous default of all
events will be used. Also allows silent query for p.simulations.query(),
useful when calling query often and keeping output down.
Added fast_unsafe as a setting to p.viz.nb’s shotgather and
custom_gather, to visualize data not on the most dense but on the most sparse
time axis of the selected datasets. This might alias data.
Fix a bug when computing misfits would not honor
receiver_sampling_rate_in_time_steps of a simulation configuration. By
default, Salvus will now drop the final data point if it does not lie on the
regular time grid of the subsampled simulation output, e.g. with 100 time
steps, but with a receiver sampling interval of 11. These are the sampling
rates that can be set via:
sn.WaveformSimulationConfiguration(
receiver_sampling_rate_in_time_steps=11, ...
)
To recreate the previous behavior, use
EventData.get_waveform_data(..., enforce_regular_time_grid=False), but note
that the resulting data will only be regularly spaced for all but the last
sample.
EventData’s get_time_axis_from_meta_json now optionally allows passing which
output type the time axis needs to be retrieved for, defaulting to the
simulation’s time axis (no subsampling).
Improve the error reporting for re-running simulations in SalvusProject with
modified outputs in the extra_output_configuration.
Improve the error message when trying to load a project from a path that either does not exist or is not a directory.
Speed up the generation of input files and hashes of simulations. This should give a noticeable improvement for simulations with event-dependent sources and many events.
In addition, a utility to simultaneously query the output directories for several events has been added:
p.simulations.get_simulation_output_directories(
simulation_configuration="my_simulation",
events=p.events.list()
)Changes to Experimental Features
Added generic salvus.material.from_params() and
salvus.material.from_dataset() methods that will automatically find and
initialize the appropriate material class.
Salvus now supports a new way of launching simulations using
p.simulations.run(). This function waits for all simulations to finish before
returning and enables a new way of parallelism.
In addition to specifying the site configuration with sn.SiteConfig, this new
function can also run several simulations in parallel on a local (or ssh)
system, which can give a substantial speed up for use cases with many small
simulations.
Usage example:
task_chain_config = TaskChainSiteConfig(
site_name="test_site",
number_of_parallel_workers=5,
ranks_per_salvus_simulation=2,
max_threads_per_worker=2,
shared_file_system=True,
)
p.simulations.run(
events=p.events.list(),
simulation_configuration="my_simulation",
site_config=task_chain_config,
)
The feature is currently still experimental. Additional output settings are not
yet supported and we recommend using p.simulations.launch() for those
instead.