%matplotlib inline
import os
from functools import partial
from pathlib import Path
import h5py
import matplotlib.pyplot as plt
import numpy as np
import salvus.namespace as sn
import salvus.toolbox.toolbox as st
SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")
def get_basic_mesh(dim: int, epd: int = 20) -> sn.UnstructuredMesh:
"""Get a simple mesh to outline allowed parameter types.
Parameters
----------
dim : int
Dimension of the mesh.
epd : int, optional
Elements per dimension, by default 20
Returns
-------
um.UnstructuredMesh
An unstructured mesh free of any parameters.
"""
x = 2.0
h = x / float(epd)
vp = 1000.0
if dim == 2:
mesh = sn.simple_mesh.basic_mesh.CartesianHomogeneousAcoustic2D(
x_max=x,
y_max=x,
rho=1000.0,
vp=vp,
max_frequency=0.5 * vp / h,
tensor_order=4,
).create_mesh()
elif dim == 3:
mesh = sn.simple_mesh.basic_mesh.CartesianHomogeneousAcoustic3D(
x_max=x,
y_max=x,
z_max=x,
rho=1000.0,
vp=vp,
max_frequency=0.5 * vp / h,
tensor_order=4,
).create_mesh()
# Delete the material properties as they will be added later on.
mesh.elemental_fields.clear()
return mesh
vs = 500.0
vp = 1000.0
rho = 1000.0
stf = sn.simple_config.stf.Ricker(center_frequency=2e3)
src_scalar_2d = sn.simple_config.source.cartesian.ScalarPoint2D(
f=1, x=1, y=1, source_time_function=stf
)
src_scalar_3d = sn.simple_config.source.cartesian.ScalarPoint3D(
f=1, x=1, y=1, z=1, source_time_function=stf
)
src_vector_2d = sn.simple_config.source.cartesian.VectorPoint2D(
fx=1, fy=1, x=1, y=1, source_time_function=stf
)
src_vector_3d = sn.simple_config.source.cartesian.VectorPoint3D(
fx=1, fy=1, fz=1, x=1, y=1, z=1, source_time_function=stf
)
api.run
function. We'll
be running the function many times with mostly the same setup, so this is a nice
space saving method.run_salvus = partial(
sn.api.run, ranks=2, get_all=True, site_name=SALVUS_FLOW_SITE_NAME
)
simulation.Waveform
object with values which will
be re-used.w = sn.simple_config.simulation.Waveform()
w.domain.dimension = 2
w.output.volume_data.format = "hdf5"
w.output.volume_data.filename = "output.h5"
w.output.volume_data.sampling_interval_in_time_steps = 100
fluid
flag set to 1.# Generate the mesh.
m = get_basic_mesh(2)
# Attach parameter to the nodes of each element.
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("VP", par_template * vp)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.ones(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["phi"]
w.physics.wave_equation.point_source = [src_scalar_2d]
# Run the solver.
output_folder = Path("acoustic_rhovp")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder)
# Visualize the results.
f, ax = plt.subplots(1, 1)
ax.set_aspect("equal")
t, da0 = st.visualize_wavefield_2d(output_file, "phi")
ax.tricontourf(t, da0[-1, :])
SalvusJob `job_2411151306195271_1a3afd2b08` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32 -> Current Task: Time loop complete* Downloaded 529.4 KB of results to `acoustic_rhovp`. * Total run time: 0.90 seconds. * Pure simulation time: 0.47 seconds.
<matplotlib.tri._tricontour.TriContourSet at 0x71c0c23108d0>
# Re-parameterize as m0 and m1.
m0, m1 = (1 / rho) / vp**2, 1 / rho
# Generate the mesh.
m = get_basic_mesh(2)
# Attach parameter to the nodes of each element.
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("M0", par_template * m0)
m.attach_field("M1", par_template * m1)
m.attach_field("fluid", np.ones(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["phi"]
w.physics.wave_equation.point_source = [src_scalar_2d]
# Run the solver.
output_folder = Path("acoustic_linear")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder)
# Visualize the results.
f, ax = plt.subplots(1, 1)
ax.set_aspect("equal")
t, da1 = st.visualize_wavefield_2d(output_file, "phi")
ax.tricontourf(t, da1[-1, :])
# All parameterizations should have produced the same output.
np.testing.assert_allclose(da0, da1, atol=1e-3)
SalvusJob `job_2411151306242339_51c0227540` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32 -> Current Task: Time loop complete* Downloaded 529.4 KB of results to `acoustic_linear`. * Total run time: 0.71 seconds. * Pure simulation time: 0.43 seconds.
# Generate the mesh.
m = get_basic_mesh(2)
# Attach parameter to the nodes of each element.
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("VP", par_template * vp)
m.attach_field("VS", par_template * vs)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.zeros(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["displacement"]
w.physics.wave_equation.point_source = [src_vector_2d]
# Run the solver.
output_folder = Path("elastic_vpvsrho")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder)
# Visualize the results.
f, ax = plt.subplots(1, 1)
ax.set_aspect("equal")
t, de0 = st.visualize_wavefield_2d(output_file, "displacement")
ax.tricontourf(t, de0[-1, :])
SalvusJob `job_2411151306235046_8009794064` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32 -> Current Task: Time loop complete* Downloaded 681.1 KB of results to `elastic_vpvsrho`. * Total run time: 0.71 seconds. * Pure simulation time: 0.53 seconds.
<matplotlib.tri._tricontour.TriContourSet at 0x71c102eecdd0>
# Generate the mesh.
m = get_basic_mesh(2)
# Attach parameter to the nodes of each element.
mu = rho * vs**2
lam = rho * vp**2 - 2 * mu
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("LAMBDA", par_template * lam)
m.attach_field("MU", par_template * mu)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.zeros(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["displacement"]
w.physics.wave_equation.point_source = [src_vector_2d]
# Run the solver.
output_folder = Path("elastic_lambdamurho")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder)
# Visualize the results.
f, ax = plt.subplots(1, 1)
ax.set_aspect("equal")
t, de1 = st.visualize_wavefield_2d(output_file, "displacement")
ax.tricontourf(t, de1[-1, :])
SalvusJob `job_2411151306320638_0996570363` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32 -> Current Task: Time loop complete* Downloaded 681.1 KB of results to `elastic_lambdamurho`. * Total run time: 0.76 seconds. * Pure simulation time: 0.48 seconds.
<matplotlib.tri._tricontour.TriContourSet at 0x71c0c6ec29d0>
# Generate the mesh.
m = get_basic_mesh(2)
# Attach parameter to the nodes of each element.
mu = rho * vs**2
kap = rho * (vp**2 - 4 / 3 * vs**2)
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("KAPPA", par_template * kap)
m.attach_field("MU", par_template * mu)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.zeros(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["displacement"]
w.physics.wave_equation.point_source = [src_vector_2d]
# Run the solver.
output_folder = Path("elastic_kappamurho")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder)
# Visualize the results.
f, ax = plt.subplots(1, 1)
ax.set_aspect("equal")
t, de2 = st.visualize_wavefield_2d(output_file, "displacement")
ax.tricontourf(t, de2[-1, :])
# All parameterizations should have produced the same output.
np.testing.assert_allclose(de0, de1, atol=1e-7)
np.testing.assert_allclose(de1, de2, atol=1e-7)
SalvusJob `job_2411151306445415_443e1d5a5f` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32 -> Current Task: Time loop complete* Downloaded 681.1 KB of results to `elastic_kappamurho`. * Total run time: 0.72 seconds. * Pure simulation time: 0.54 seconds.
w = sn.simple_config.simulation.Waveform()
w.domain.dimension = 3
w.output.volume_data.format = "hdf5"
w.output.volume_data.filename = "output.h5"
w.output.volume_data.sampling_interval_in_time_steps = 100
fluid
flag set to 1.# Generate the mesh.
m = get_basic_mesh(3)
# Attach parameter to the nodes of each element.
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("VP", par_template * vp)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.ones(m.nelem))
# Attach the mesh.
w.set_mesh(m)
w.output.volume_data.fields = ["phi"]
w.physics.wave_equation.point_source = [src_scalar_3d]
# Run the solver.
output_folder = Path("acoustic_rhovp")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder, overwrite=True)
# Read the results.
with h5py.File(output_file, "r") as fh:
da0 = fh["/volume/phi"][:]
SalvusJob `job_2411151306055267_29dbf07810` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32
* Downloaded 66.0 MB of results to `acoustic_rhovp`. * Total run time: 7.39 seconds. * Pure simulation time: 6.18 seconds.
# Re-parameterize as m0 and m1.
m0, m1 = (1 / rho) / vp**2, 1 / rho
# Generate the mesh.
m = get_basic_mesh(3)
# Attach parameter to the nodes of each element.
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("M0", par_template * m0)
m.attach_field("M1", par_template * m1)
m.attach_field("fluid", np.ones(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["phi"]
w.physics.wave_equation.point_source = [src_scalar_3d]
# Run the solver.
output_folder = Path("acoustic_linear")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder, overwrite=True)
# Visualize the results.
with h5py.File(output_file, "r") as fh:
da1 = fh["/volume/phi"][:]
# All parameterizations should have produced the same output.
da0_l2 = np.linalg.norm(da0)
da1_l2 = np.linalg.norm(da1)
np.testing.assert_allclose(da0_l2, da1_l2, atol=da0_l2 * 1e-6)
SalvusJob `job_2411151306018645_91f8ae2541` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32
* Downloaded 66.0 MB of results to `acoustic_linear`. * Total run time: 6.34 seconds. * Pure simulation time: 5.87 seconds.
# Generate the mesh.
m = get_basic_mesh(3)
# Attach parameter to the nodes of each element.
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("VP", par_template * vp)
m.attach_field("VS", par_template * vs)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.zeros(m.nelem))
# # Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["displacement"]
w.physics.wave_equation.point_source = [src_vector_3d]
# # Run the solver.
output_folder = Path("elastic_vpvsrho")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder, overwrite=True)
# Visualize the results.
with h5py.File(output_file, "r") as fh:
de0 = fh["/volume/displacement"][:]
SalvusJob `job_2411151306899198_02a564c4d5` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32
* Downloaded 89.4 MB of results to `elastic_vpvsrho`. * Total run time: 11.59 seconds. * Pure simulation time: 10.90 seconds.
# Generate the mesh.
m = get_basic_mesh(3)
# Attach parameter to the nodes of each element.
mu = rho * vs**2
lam = rho * vp**2 - 2 * mu
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("LAMBDA", par_template * lam)
m.attach_field("MU", par_template * mu)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.zeros(m.nelem))
# # Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["displacement"]
w.physics.wave_equation.point_source = [src_vector_3d]
# Run the solver.
output_folder = Path("elastic_lambdamurho")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder, overwrite=True)
# # Visualize the results.
with h5py.File(output_file, "r") as fh:
de1 = fh["/volume/displacement"][:]
SalvusJob `job_2411151307050712_6e7e03694a` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32
* Downloaded 89.4 MB of results to `elastic_lambdamurho`. * Total run time: 12.72 seconds. * Pure simulation time: 12.20 seconds.
# Generate the mesh.
m = get_basic_mesh(3)
# Attach parameter to the nodes of each element.
mu = rho * vs**2
kap = rho * (vp**2 - (4 / 3) * vs**2)
par_template = np.ones_like(m.get_element_nodes()[:, :, 0])
m.attach_field("KAPPA", par_template * kap)
m.attach_field("MU", par_template * mu)
m.attach_field("RHO", par_template * rho)
m.attach_field("fluid", np.zeros(m.nelem))
# Attach the mesh and set some custom output.
w.set_mesh(m)
w.output.volume_data.fields = ["displacement"]
w.physics.wave_equation.point_source = [src_vector_3d]
# Run the solver.
output_folder = Path("elastic_kappamurho")
output_file = output_folder / "output.h5"
run_salvus(input_file=w, output_folder=output_folder, overwrite=True)
# Visualize the results.
with h5py.File(output_file, "r") as fh:
de2 = fh["/volume/displacement"][:]
# All parameterizations should have produced the same output.
np.testing.assert_allclose(de0, de1, atol=1e-7)
np.testing.assert_allclose(de1, de2, atol=1e-7)
SalvusJob `job_2411151307508861_a77bbd36dd` running on `local` with 2 rank(s). Site information: * Salvus version: 2024.1.2 * Floating point size: 32
* Downloaded 89.4 MB of results to `elastic_kappamurho`. * Total run time: 12.93 seconds. * Pure simulation time: 11.67 seconds.