This documentation is not for the latest stable Salvus version.
import matplotlib.pyplot as plt
import numpy as np
import os
import pathlib
import xarray as xr
import salvus.namespace as sn
# Run simulations on this site.
SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")xarray data set which will later be interpolated onto our numerical meshes.# Grid points of the velocity model.
# NOT the grid point of the simulation!
nx, ny = 200, 200
# Create a coordinate grid.
x = np.linspace(-100.0, +100.0, nx)
y = np.linspace(-100.0, +100.0, nx)
xx, yy = np.meshgrid(x, y, indexing="ij")
# Simplistic 5 parameter model with a depth gradient and
# some sinusoidal perturbation.
# This is just an example but this would be the place to add
# your own velocity model.
vp = 1500.0 * np.ones_like(xx) - yy * 0.1 + np.sin(xx / 8 + 0.5) * 2
vs = 1000.0 * np.ones_like(xx) - yy * 0.1 + np.sin(xx / 12 - 0.3) * 2
rho = 980.0 * np.ones_like(xx) - yy * 0.1 + np.sin(xx / 15 + 1) * 2
qkappa = 75.0 * np.ones_like(xx) - yy * 0.1 + np.sin(xx / 6) * 2
qmu = 75.0 * np.ones_like(xx) - yy * 0.1 + np.sin(xx / 10 - 1.2) * 2
# We build a full visco-elastic model with all fields, but will drop
# unneeded fields later on as needed.
dataset = xr.Dataset(
    data_vars={
        "vp": (["x", "y"], vp),
        "vs": (["x", "y"], vs),
        "rho": (["x", "y"], rho),
        "qkappa": (["x", "y"], qkappa),
        "qmu": (["x", "y"], qmu),
    },
    coords={"x": x, "y": y},
)
# Have a look at the Qmu model.
plt.figure(figsize=(10, 8))
dataset.qmu.T.plot()
plt.show()# Either load an existing project or create a new one.
p = sn.Project.from_domain(
    path="project",
    # Should match the volume model.
    domain=sn.domain.dim2.BoxDomain(x0=-100, x1=100, y0=-100, y1=100),
    load_if_exists=True,
)displacement, while the acoustic event requires a scalar source and records phi.src = sn.simple_config.source.cartesian.MomentTensorPoint2D(
    x=0, y=0, mxx=1.0, myy=1.0, mxy=0.0
)
recs = sn.simple_config.receiver.cartesian.collections.RingPoint2D(
    x=0, y=0, radius=75.0, count=20, fields=["displacement"]
)
p += sn.Event(event_name="event_ela", sources=src, receivers=recs)
src = sn.simple_config.source.cartesian.ScalarPoint2D(x=0, y=0, f=1.0)
recs = sn.simple_config.receiver.cartesian.collections.RingPoint2D(
    x=0, y=0, radius=75.0, count=20, fields=["phi"]
)
p += sn.Event(event_name="event_aco", sources=src, receivers=recs)
p.viz.nb.domain()dataset above, and we just drop the
fields that are not needed.p += sn.model.volume.cartesian.GenericModel(
    name="model_elastic_with_Q", data=dataset
)
# An elastic simulation without attenuation neither requires QMU not QKAPPA
p += sn.model.volume.cartesian.GenericModel(
    name="model_elastic_without_Q", data=dataset.drop_vars(["qmu", "qkappa"])
)
# An acoustic simulation without attenuation neither requires Q nor VS
p += sn.model.volume.cartesian.GenericModel(
    name="model_acoustic_without_Q",
    data=dataset.drop_vars(["qmu", "qkappa", "vs"]),
)
# An acoustic simulation with attenuation neither requires QMU nor VS,
# but requires QKAPPA
p += sn.model.volume.cartesian.GenericModel(
    name="model_acoustic_with_Q", data=dataset.drop_vars(["qmu", "vs"])
)# A few wave-lengths are needed to see an attenuating effect.
center_frequency = 100.0
# Setup four simulations:
# Acoustic / elastic and with or without attenuation.
for medium in ["acoustic", "elastic"]:
    for attenuation in [True, False]:
        if attenuation:
            simulation_name = f"{medium}_with_attenuation"
            mc = sn.ModelConfiguration(
                background_model=None,
                volume_models=f"model_{medium}_with_Q",
                # Attenuation results in slightly frequency dependent wave speed.
                # Thus one must specify at what frequency they are specified.
                # They are often given at 1 Hz.
                linear_solids=sn.LinearSolids(reference_frequency=1.0),
            )
        else:
            simulation_name = f"{medium}_without_attenuation"
            mc = sn.ModelConfiguration(
                background_model=None,
                volume_models=f"model_{medium}_without_Q",
            )
        p += sn.SimulationConfiguration(
            name=simulation_name,
            max_frequency_in_hertz=center_frequency * 2.0,
            elements_per_wavelength=2.0,
            model_configuration=mc,
            event_configuration=sn.EventConfiguration(
                wavelet=sn.simple_config.stf.Ricker(
                    center_frequency=center_frequency
                ),
                waveform_simulation_configuration=sn.WaveformSimulationConfiguration(
                    end_time_in_seconds=0.07,
                    # This is to tell the simulation to actually
                    # simulate with attenuation or not.
                    attenuation=attenuation,
                ),
            ),
        )p.viz.nb.simulation_setup("elastic_with_attenuation")[2024-03-15 09:19:10,322] INFO: Creating mesh. Hang on.
<salvus.mesh.unstructured_mesh.UnstructuredMesh at 0x7f191c8f3590>
event_ela has a moment tensor source, hence requires an elastic medium, while event_aco uses a scalar source for an acoustic medium.for name in [
    "elastic_with_attenuation",
    "elastic_without_attenuation",
]:
    p.simulations.launch(
        simulation_configuration=name,
        events="event_ela",
        site_name=SALVUS_FLOW_SITE_NAME,
        ranks_per_job=1,
    )
for name in [
    "acoustic_with_attenuation",
    "acoustic_without_attenuation",
]:
    p.simulations.launch(
        simulation_configuration=name,
        events="event_aco",
        site_name=SALVUS_FLOW_SITE_NAME,
        ranks_per_job=1,
    )
# Wait for all simulations to finish
p.simulations.query(block=True)[2024-03-15 09:19:11,675] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2403150919872385_b1b8659bf2@local [2024-03-15 09:19:12,025] INFO: Creating mesh. Hang on. [2024-03-15 09:19:12,226] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2403150919233397_41ab624913@local [2024-03-15 09:19:12,321] INFO: Creating mesh. Hang on. [2024-03-15 09:19:12,536] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2403150919542647_a329cab04c@local [2024-03-15 09:19:12,656] INFO: Creating mesh. Hang on. [2024-03-15 09:19:12,816] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2403150919821402_73d4ad1090@local
True
p.viz.waveforms(
    event="event_ela",
    receiver_name="XX.A0006",
    data=["elastic_with_attenuation", "elastic_without_attenuation"],
    receiver_field="displacement",
)
plt.show()p.viz.waveforms(
    event="event_aco",
    receiver_name="XX.A0006",
    data=["acoustic_with_attenuation", "acoustic_without_attenuation"],
    receiver_field="phi",
)
plt.show()