SalvusCompute
where the coordinates are already known exactly. In many scenarios this is not necessarily the case. Imaging a mesh with potentially arbitrarily shaped and curved elements and you want to exactly locate a source or receiver relative to the local surface or for example at the ocean bottom. This problem is dependent on the exact mesh used for the simulation.# This line helps with tab-completion of the simple_config objects.
# The IPython/Jupyter project default to a differnet inference based
# tab completion engine which unfortunately does not yet fully work
# with SalvusFlow. This is completely optional and a convenience
# option.
%config Completer.use_jedi = False
# SalvusFlow and SalvusMesh convenience interfaces.
from salvus.flow import simple_config
from salvus.mesh import simple_mesh
# We'll also use numpy.
import numpy as np
SalvusCompute
these are used to specify boundary conditions, here we will use them to locate source and receiver relative to them. The following example mesh has 4 side-sets, each denoting one side of the mesh. Please note, that the names are arbitrary and mesh dependent.SideSet
and all the coordinates are replaced with a point
, direction
, side_set_name
, and offset
parameters.simple_config.receiver.cartesian.SideSetPoint2D
simple_config.receiver.cartesian.SideSetPoint3D
simple_config.source.cartesian.SideSetScalarPoint2D
simple_config.source.cartesian.SideSetScalarPoint3D
simple_config.source.cartesian.SideSetScalarGradientPoint2D
simple_config.source.cartesian.SideSetScalarGradientPoint3D
simple_config.source.cartesian.SideSetVectorPoint2D
simple_config.source.cartesian.SideSetVectorPoint3D
simple_config.source.cartesian.SideSetMomentTensorPoint2D
simple_config.source.cartesian.SideSetMomentTensorPoint3D
mesh = simple_mesh.basic_mesh.CartesianFromBm2D(
bm_file="prem_iso_no_crust",
x_max=6371e3,
y_max=6371e3,
max_frequency=1 / 1500.0,
elements_per_wavelength=2.0,
tensor_order=4,
).create_mesh()
# Add a nice curve to the mesh surface.
# Note how it would not longer be trivial to add sources
# or receivers exactly at the surface of the mesh!
x_range = mesh.points[:, 0].ptp()
mesh.points[:, 1] += np.sin(mesh.points[:, 0] / x_range * 2 * np.pi) * 3e5
mesh
<salvus.mesh.data_structures.unstructured_mesh.unstructured_mesh.UnstructuredMesh object at 0x7f9d2aa44bd0>
# One receiver at the top, one at the bottom.
recs = [
simple_config.receiver.cartesian.SideSetPoint2D(
point=(3e6, 0.0),
# Locate vertically.
direction=(0.0, 1.0),
# Top side-set.
side_set_name="y1",
# Followed by the normal receiver coordinates.
station_code="A1",
fields=["displacement"],
),
# Second receiver.
simple_config.receiver.cartesian.SideSetPoint2D(
point=(5e6, 0.0),
# Note that the direction vector can also be specified as the
# name of the coordinate axis.
direction="y",
# Bottom
side_set_name="y0",
# Followed by the normal receiver coordinates.
station_code="A2",
fields=["displacement"],
),
]
srcs = simple_config.source.cartesian.SideSetVectorPoint2D(
point=[2e6, 0.0],
direction="y",
side_set_name="y1",
# Bury it a bit.
offset=-2e6,
fx=1.0,
fy=2.0,
source_time_function=simple_config.stf.Delta(),
)
w = simple_config.simulation.Waveform()
w.set_mesh(mesh)
w.add_receivers(recs)
w.add_sources(srcs)
w
<salvus.flow.simple_config.simulation.waveform.Waveform object at 0x7f9dfab02d90>