import numpy as np
import os
import salvus.namespace as sn
# Run simulations on this site.
SALVUS_FLOW_SITE_NAME = os.environ.get("SITE_NAME", "local")
# 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=0, x1=3000, y0=-1000, y1=0),
load_if_exists=True,
)
bm
model file.%%writefile layered_model.bm
NAME radial_model
ACOUSTIC true
UNITS m
COLUMNS depth rho vp
0.0 1000.0 1500.0
200.0 1000.0 1500.0
200.0 1300.0 1900.0
500.0 1300.0 1900.0
500.0 2200.0 3200.0
4000.0 2200.0 3200.0
Writing layered_model.bm
%%writefile layered_model_ani.bm
NAME radial_model
ACOUSTIC true
ANISOTROPIC true
UNITS m
COLUMNS depth rho vpv vph
0.0 1000.0 1500.0 1500.0
200.0 1000.0 1500.0 1500.0
200.0 1300.0 1900.0 2100.0
500.0 1300.0 1900.0 2100.0
500.0 2200.0 3200.0 3500.0
4000.0 2200.0 3200.0 3500.0
Writing layered_model_ani.bm
VPV
and VPH
.%%writefile layered_model_fake_ani.bm
NAME radial_model
ACOUSTIC true
ANISOTROPIC true
UNITS m
COLUMNS depth rho vpv vph
0.0 1000.0 1500.0 1500.0
200.0 1000.0 1500.0 1500.0
200.0 1300.0 1900.0 1900.0
500.0 1300.0 1900.0 1900.0
500.0 2200.0 3200.0 3200.0
4000.0 2200.0 3200.0 3200.0
Writing layered_model_fake_ani.bm
for name, bm in zip(
["isotropic", "anisotropic", "fake-anisotropic"],
["layered_model.bm", "layered_model_ani.bm", "layered_model_fake_ani.bm"],
):
p.add_to_project(
sn.SimulationConfiguration(
name=name,
max_frequency_in_hertz=20.0,
elements_per_wavelength=1.5,
model_configuration=sn.ModelConfiguration(
background_model=sn.model.background.one_dimensional.FromBm(
filename=bm, reference_datum=0.0
),
),
event_configuration=sn.EventConfiguration(
wavelet=sn.simple_config.stf.Ricker(center_frequency=10.0),
waveform_simulation_configuration=sn.WaveformSimulationConfiguration(
end_time_in_seconds=1.5,
),
),
absorbing_boundaries=sn.AbsorbingBoundaryParameters(
reference_velocity=2200.0,
reference_frequency=10.0,
number_of_wavelengths=7,
),
),
)
p.viz.nb.simulation_setup("anisotropic")
[2025-05-21 02:38:37,396] INFO: Creating mesh. Hang on.
<salvus.mesh.data_structures.unstructured_mesh.unstructured_mesh.UnstructuredMesh object at 0x72b092065910>
UnstructuredMeshSimulationConfiguration
.def convert_thomsen_params_to_vti_tensor(
dim: int,
rho: np.ndarray,
vp: np.ndarray,
delta: np.ndarray,
epsilon: np.ndarray,
):
if dim == 2:
model = {
"M0": 1 / (vp**2 * rho),
"D11": (1 + 2 * epsilon) / rho,
"D12": (delta - epsilon) / rho,
"D22": 1 / rho,
}
elif dim == 3:
model = {
"M0": 1 / (vp**2 * rho),
"D11": (1 + 2 * epsilon) / rho,
"D12": np.zeros_like(rho),
"D13": (delta - epsilon) / rho,
"D22": (1 + 2 * epsilon) / rho,
"D23": (delta - epsilon) / rho,
"D33": 1 / rho,
}
return model
def interpolate_vti_model_onto_mesh(mesh: sn.UnstructuredMesh):
if "VPV" in mesh.elemental_fields.keys():
vti_model = convert_thomsen_params_to_vti_tensor(
dim=2,
rho=mesh.elemental_fields["RHO"],
vp=mesh.elemental_fields["VPV"],
delta=0.5
* (
mesh.elemental_fields["VPH"] ** 2
/ mesh.elemental_fields["VPV"] ** 2
- 1.0
),
epsilon=0.5
* (
mesh.elemental_fields["VPH"] ** 2
/ mesh.elemental_fields["VPV"] ** 2
- 1.0
),
)
for k, v in vti_model.items():
mesh.elemental_fields[k] = v
del mesh.elemental_fields["VPV"]
del mesh.elemental_fields["VPH"]
del mesh.elemental_fields["RHO"]
else:
vti_model = convert_thomsen_params_to_vti_tensor(
dim=2,
rho=mesh.elemental_fields["RHO"],
vp=mesh.elemental_fields["VP"],
delta=np.zeros_like(mesh.elemental_fields["VP"]),
epsilon=np.zeros_like(mesh.elemental_fields["VP"]),
)
for k, v in vti_model.items():
mesh.elemental_fields[k] = v
del mesh.elemental_fields["VP"]
del mesh.elemental_fields["RHO"]
return mesh
mesh = p.simulations.get_mesh("isotropic")
mesh = interpolate_vti_model_onto_mesh(mesh)
p.add_to_project(
sn.UnstructuredMeshSimulationConfiguration(
unstructured_mesh=mesh,
name="thomsen-isotropic",
event_configuration=p.entities.get(
"simulation_configuration", "anisotropic"
).event_configuration,
)
)
mesh = p.simulations.get_mesh("anisotropic")
mesh = interpolate_vti_model_onto_mesh(mesh)
p.add_to_project(
sn.UnstructuredMeshSimulationConfiguration(
unstructured_mesh=mesh,
name="thomsen-anisotropic",
event_configuration=p.entities.get(
"simulation_configuration", "anisotropic"
).event_configuration,
)
)
[2025-05-21 02:38:37,674] INFO: Creating mesh. Hang on.
src = sn.simple_config.source.cartesian.ScalarPoint2D(x=1500, y=0, f=1.0)
recs = sn.simple_config.receiver.cartesian.collections.ArrayPoint2D(
x=np.linspace(100, 2900, 141), y=np.zeros(141), fields=["phi"]
)
p += sn.Event(event_name="event", sources=src, receivers=recs)
p.viz.nb.domain()
for name in [
"isotropic",
"anisotropic",
"fake-anisotropic",
"thomsen-anisotropic",
"thomsen-isotropic",
]:
p.simulations.launch(
simulation_configuration=name,
events=p.events.list(),
site_name=SALVUS_FLOW_SITE_NAME,
ranks_per_job=1,
)
p.simulations.query(block=True)
[2025-05-21 02:38:37,890] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2505210238001645_3381f1736b@local
[2025-05-21 02:38:39,627] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2505210238632192_434e2d8843@local
[2025-05-21 02:38:41,627] INFO: Creating mesh. Hang on. [2025-05-21 02:38:41,701] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2505210238706163_55d56ea73d@local
[2025-05-21 02:38:43,372] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2505210238376590_0b7fa5835e@local
[2025-05-21 02:38:45,129] INFO: Submitting job ... Uploading 1 files... 🚀 Submitted job_2505210238133721_a16e021a68@local
p.viz.nb.waveforms(
data=["isotropic", "fake-anisotropic", "thomsen-isotropic"],
receiver_field="phi",
)
p.viz.nb.waveforms(
data=["anisotropic", "thomsen-anisotropic"],
receiver_field="phi",
)
p.viz.nb.waveforms(
data=["isotropic", "anisotropic"],
receiver_field="phi",
)
p.waveforms.get(data_name="isotropic", events=p.events.list())[0].plot(
component="A",
receiver_field="phi",
plot_types=["shotgather"],
)
p.waveforms.get(data_name="anisotropic", events=p.events.list())[0].plot(
component="A",
receiver_field="phi",
plot_types=["shotgather"],
)