Mondaic

Salvus 2024.1.1

Released: 2024-07-02

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

SalvusFlow

Updated the Salvus Jupyter notebook snippets collection now works with Jupyter notebooks >= 7 as well as JupyterLab.

%load_ext salvus
%salvus_snippets
SalvusFlow

Added 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,
  )
SalvusMesh

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.

SalvusMesh

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.

SalvusMesh

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.

SalvusMesh

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.

SalvusProject

Fix a bug where the ocean layer would not be positioned correctly in cartesian domains with strict top and bottom domain boundaries.

SalvusProject

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,
    )
SalvusProject

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.

SalvusProject

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.

SalvusProject

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).

SalvusProject

Improve the error reporting for re-running simulations in SalvusProject with modified outputs in the extra_output_configuration.

SalvusProject

Improve the error message when trying to load a project from a path that either does not exist or is not a directory.

SalvusProject

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

SalvusMaterial

Added generic salvus.material.from_params() and salvus.material.from_dataset() methods that will automatically find and initialize the appropriate material class.

SalvusProject

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.