SimulationConfiguration
object, and investigate how high-order accurate topography / material interpolation can be used to improve simulation performance. To accomplish this, we'll focus on a real-life use case using the area around Mt. St. Helens in Washington state as an example. Of course please feel free to adapt the geographical area.%matplotlib inline
import os
import pathlib
import salvus.namespace as sn
# This notebook will use this variable to determine which
# remote site to run on.
SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")
PROJECT_DIR = "project"
UtmDomain.from_spherical_chunk
constructor that takes WGS84 coordinates and converts them to an appropriate UTM domain. The UTM zone and coordinates could of course also be specified directly.d = sn.domain.dim3.UtmDomain.from_spherical_chunk(
min_latitude=46.15,
max_latitude=46.30,
min_longitude=-122.28,
max_longitude=-122.12,
)
# Have a look at the domain to make sure it is correct.
d.plot()
# Where to download topography data to.
topo_filename = "data/gmrt_topography.nc"
# Now query data from the GMRT web service.
d.download_topography_and_bathymetry(
filename=topo_filename,
# The buffer is useful for example when adding sponge layers
# for absorbing boundaries so we recommend to always use it.
buffer_in_degrees=0.1,
resolution="default",
)
# Load the data to Salvus compatible SurfaceTopography object. It will resample
# to a regular grid and convert to the UTM coordinates of the domain.
# This will later be added to the Salvus project.
t = sn.topography.cartesian.SurfaceTopography.from_gmrt_file(
name="st_helens_topo",
data=topo_filename,
resample_topo_nx=200,
# If the coordinate conversion is very slow, consider decimating.
decimate_topo_factor=5,
# Smooth if necessary.
gaussian_std_in_meters=0.0,
# Make sure to pass the correct UTM zone.
utm=d.utm,
)
t.ds.dem.T.plot(aspect=1, size=7)
<matplotlib.collections.QuadMesh at 0x7f61fd51c550>
# Uncomment the following line to delete a
# potentially existing project for a fresh start
# !rm -rf project
p = sn.Project.from_domain(path=PROJECT_DIR, domain=d, load_if_exists=True)
SurfaceTopography
object to Salvus:p += t
p.entities.list("topography_model")
['st_helens_topo']
SideSet
source and receiver classes. The functionality of these classes is documented here. Essentially, they help when the actual surface of the domain is non-trivial, as is the case in this example. When these sources and receivers are associated with a mesh, a small optimization problem is solved to ensure that they are placed exactly at the surface of the deformed mesh, plus or minus any offset one might specify. Here we specify the entities in UTM coordinates, place the source 1000 meters below the free surface, and place a line of 50 receivers directly at the free surface.# Src / Rec reference coordinates.
src_x, src_y, src_z = 562700.0, 5112500.0, 4000.0
rec_x, rec_y, rec_z = 564700.0, 5115500.0, 4000.0
# Place an explosive source 1000 m below the free surface.
src = sn.simple_config.source.cartesian.SideSetMomentTensorPoint3D(
point=(src_x, src_y, src_z),
direction=(0, 0, 1),
side_set_name="z1",
mxx=1e21,
myy=1e21,
mzz=1e21,
myz=0.0,
mxz=0.0,
mxy=0.0,
offset=-1000.0,
)
# Place a line of receivers at the free surface.
rec = [
sn.simple_config.receiver.cartesian.SideSetPoint3D(
point=(rec_x, rec_y + _i * 100, rec_z),
direction=(0, 0, 1),
side_set_name="z1",
fields=["velocity"],
station_code=f"XX_{_i}",
)
for _i in range(50)
]
# Add the event collection to the project.
p += sn.EventCollection.from_sources(sources=[src], receivers=rec)
bm = sn.model.background.homogeneous.IsotropicElastic(
rho=2600.0, vp=3000.0, vs=1875.5
)
mc = sn.model.ModelConfiguration(background_model=bm)
ec = sn.EventConfiguration(
wavelet=sn.simple_config.stf.Ricker(center_frequency=1.0),
waveform_simulation_configuration=sn.WaveformSimulationConfiguration(
end_time_in_seconds=6.0
),
)
TopographyConfiguration
object. As is true with the ModelConfiguration
, this object takes as arguments one or more topography models. A background topography model does not have much of a meaning, so it is not defined for topography configurations.tc = sn.topography.TopographyConfiguration(topography_models="st_helens_topo")
ab = sn.AbsorbingBoundaryParameters(
reference_velocity=3000.0,
reference_frequency=5.0,
number_of_wavelengths=3.5,
)
p += sn.SimulationConfiguration(
name="sim_1st_order_topo",
tensor_order=1,
model_configuration=mc,
event_configuration=ec,
absorbing_boundaries=ab,
elements_per_wavelength=1,
max_depth_in_meters=2000.0,
max_frequency_in_hertz=2.0,
topography_configuration=tc,
)
p.viz.nb.simulation_setup("sim_1st_order_topo", ["event_0000"])
[2023-05-29 19:43:36,151] INFO: Creating mesh. Hang on.