This documentation is not for the latest stable Salvus version.
period
here) and re-running the whole notebook could also be used to run realistic and large-scale simulations.pyasdf
and obspy
Python libraries which can be installed either via pip
or via conda
.import os
import pyasdf
from salvus.flow import api, simple_config
from salvus.mesh import simple_mesh
SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")
# Controls the dominant period of the mesh and the width
# of the source time function. It is given in seconds.
period = 4000.0
# We'll first build a mesh using the simple_mesh interface. Some notes:
# - At these period we don't require a crust. Adding a 3D model is the topic of
# another tutorial.
# - Higher order shapes and models better approximate the sphere. With order 4
# we achieve a very good approximation of it even with only very few
# elements.
m = simple_mesh.basic_mesh.GlobalBuiltIn3D(
model="prem_ani_no_crust", period=period, tensor_order=4
)
# In order to make it a bit more interesting we'll create an
# elliptic mesh. This is the WGS84 ellipsoid.
m.spherical.ellipticity = 0.0033528106647474805
# This is an important setting. The more elements per wavelength the more
# accurate the solution. 2 is a conservative value and the default. Many global
# seismologist only use 1 element per wavelength which ends up being 16 times
# cheaper in terms of simulation cost but is still usable in many scenarios.
m.basic.elements_per_wavelength = 2.0
# Tohuko-Oki earthquake. Information is taken from the GCMT catalog
# which unfortunately does not offer a proper web service.
source = simple_config.source.seismology.SideSetMomentTensorPoint3D(
latitude=37.5200,
longitude=143.0500,
depth_in_m=20000,
side_set_name="r1",
mrr=1.730000e22,
mtt=-2.810000e21,
mpp=-1.450000e22,
mrt=2.120000e22,
mrp=4.550000e22,
mtp=-6.570000e21,
source_time_function=simple_config.stf.GaussianRate(
half_duration_in_seconds=period / 2
),
)
# Create the simulation object and combine all the information.
w = simple_config.simulation.Waveform(mesh=m.create_mesh())
# Sources and receivers will be placed exactly relative to the
# local mesh surface. Please refer to the sources and receivers
# documentation for more details.
w.add_sources(source)
# Here we use a pre-compiled STATIONXML.
# Alternatively, we could use obspy's FDSN client to directly
# download GSN stations via IRIS. _GSN is the virtual GSN network
# which groups a number of actual seismic network.
# inv = obspy.clients.fdsn.Client("IRIS").get_stations(
# network="_GSN", level="station", format="text"
# )
w.add_receivers(
simple_config.receiver.seismology.parse(
"data/inventory.xml", dimensions=3, fields=["displacement"]
)
)
# Visualize it.
w
<salvus.flow.simple_config.simulation.waveform.Waveform object at 0x7f78b9cd7590>
# We use SalvusFlow to run the simulation. The site determines
# where it will run in the end. Might be the local machine, or
# a large remote cluster.
api.run(
input_file=w,
site_name=SALVUS_FLOW_SITE_NAME,
output_folder="global_simulation",
)
SalvusJob `job_2504152015525041_5a22667459` running on `local` with 4 rank(s). Site information: * Salvus version: 2024.1.3 * Floating point size: 32
* Downloaded 35.1 MB of results to `global_simulation`. * Total run time: 12.66 seconds. * Pure simulation time: 11.83 seconds.
<salvus.flow.executors.salvus_job.SalvusJob at 0x7f7964767150>
# Now we'll just randomly select a waveform to plot.
ds = pyasdf.ASDFDataSet("./global_simulation/receivers.h5")
ds.waveforms.IU_ANMO.displacement.plot()
<Figure size 800x750 with 3 Axes>