from salvus.material import elastic, orientation
import numpy as np
from salvus.material._details.material import to_solver_form
np.set_printoptions(precision=2)
AzimuthDip
orientation is one of the more common ways to specify
material orientation. It uses:orientation_1 = orientation.AzimuthDip.from_params(azimuth=0, dip=22.5)
orientation_1
<IPython.core.display.HTML object>
salvus.material.orientation.AzimuthDip
orientation_1.generate_rotation_matrix()
array([[[ 0.92, 0. , 0.38], [ 0. , 1. , 0. ], [-0.38, 0. , 0.92]]])
_ = orientation.visualize_local_bases(orientation_1)
orientation_2 = orientation.AzimuthDip.from_params(
azimuth=0, dip=np.array([0, 11.25, 22.5, 33.75, 45.0])
)
# The semi-colon at the end of the line suppresses the output in Jupyter,
# such that the figure is not printed twice.
_ = orientation.visualize_local_bases(orientation_2)
orientation_3 = orientation.AzimuthDip.from_params(
azimuth=np.array([0, 30, 60, 90]), dip=33
)
_ = orientation.visualize_local_bases(orientation_3)
AxesDips
class, which
allows you to specify:orientation_4 = orientation.AxesDips.from_params(dip_x=22.5, dip_y=12.5)
orientation_4
<IPython.core.display.HTML object>
salvus.material.orientation.AxesDips
dip_x
and dip_y
angles don't
specify the total dip of the local horizontal plane, except when one of them
is 0:orientation_5 = orientation.AxesDips.from_params(dip_x=22.5, dip_y=0)
np.allclose(
orientation_1.generate_rotation_matrix(),
orientation_5.generate_rotation_matrix(),
)
True
# But when dip_x and dip_y are both non-zero:
np.allclose(
orientation_1.generate_rotation_matrix(),
orientation_4.generate_rotation_matrix(),
)
False
orientation_5a = orientation.AxesDips.from_params(dip_x=33, dip_y=33)
orientation_5a
<IPython.core.display.HTML object>
salvus.material.orientation.AxesDips
orientation_5b = orientation.AzimuthDip.from_params(azimuth=45, dip=33)
orientation_5b
<IPython.core.display.HTML object>
salvus.material.orientation.AzimuthDip
orientation.visualize_local_bases(orientation_5a)
orientation.visualize_local_bases(orientation_5b)
<Figure size 1500x500 with 3 Axes>
np.allclose(
orientation_5a.generate_rotation_matrix(),
orientation_5b.generate_rotation_matrix(),
)
False
orientation.AzimuthDip.from_material(orientation_5a).DIP.p
42.564398528805846
orientation_5b.DIP.p
33.0
AxesDips
and AzimuthDip
orientations are unfortunately not always
sufficient to describe the orientation of a material. For example, if we
have a material that is not hexagonal, but orthotropic, monoclinic or
triclinic, we need to also keep track of the orientation of the material's
horizontal rotation about the local z-axis.AzimuthDipRake
orientation, which has the same definition as AzimuthDip
, but adds a
rake angle. The rake angle is defined as an angle measured from the
horizontal on the dipping plane (strike) for local y, or as the angle between
the down direction on the dipping plane and the local x-axis. This way, when
"facing" in the down direction on the dipping plane, local x is pointing in
your view direction, and local y is pointing to your left. The rake angle is
measured in the plane of the dip.orientation_6 = orientation.AzimuthDipRake.from_params(
azimuth=0, # Dip towards the x-axis
dip=22.5,
# Local x as to make these angles with the local down, in-plane.
rake=np.linspace(0, 30, 5),
)
orientation.visualize_local_bases(orientation_6)
<Figure size 1500x500 with 3 Axes>
DirectOrthonormalBasis
class. This class allows you to specify the local coordinate system using
three orthonormal basis vectors. This is a more general way to specify
orientation and can be useful when you have a specific coordinate system in
mind or when the other parameterizations are not sufficient.orientation_7 = orientation.DirectOrthonormalBasis.from_basis_vectors(
local_x=np.array([0, 1.0, 0]),
local_y=np.array([-1.0, 0.0, 0]),
local_z=np.array([0, 0, 1.0]),
)
orientation.visualize_local_bases(orientation_7)
<Figure size 1500x500 with 3 Axes>
orientation_8 = orientation.DirectOrthonormalBasis.from_basis_vectors(
local_x=np.array([0, 1.0, 0]),
local_y=np.array([-1.0, 0.0, 0]),
local_z=np.array([0.2, 0.2, 1.0]),
skip_orthonormalization=False,
)
orientation.visualize_local_bases(orientation_8)
orientation_8.get_basis_vectors()
(array([[ 0. , 0.98, -0.19]]), array([[-0.98, 0.04, 0.19]]), array([[0.2 , 0.19, 0.96]]))
elastic_vti_material = elastic.transversely_isotropic.Thomsen.from_params(
rho=2500, vp=5000, vs=3500, epsilon=0.23, delta=0.4, gamma=0.2
)
elastic_vti_material
<IPython.core.display.HTML object>
salvus.material.elastic.hexagonal.Thomsen
elastic_vti_material.to_tensor_components()
<IPython.core.display.HTML object>
salvus.material.elastic.hexagonal.TensorComponents
orientation_1 = orientation.AzimuthDip.from_params(azimuth=0, dip=22.5)
elastic_vti_material_oriented = elastic_vti_material.with_orientation(
orientation_1
)
elastic_vti_material_oriented
<IPython.core.display.HTML object>
abc.salvus.material.orientation.elastic.hexagonal.Thomsen
# to_solver_form(m=elastic_vti_material) # Won't work, nothing to do!
elastic_vti_material_oriented_sf = to_solver_form(
m=elastic_vti_material_oriented
)
elastic_vti_material_oriented_sf
<IPython.core.display.HTML object>
salvus.material.elastic.triclinic.TensorComponents
elastic_vti_material_oriented_sf.to_wavelength_oracle()
Constant parameter Spatially constant Value: 3.4e+03
isinstance(
elastic_vti_material_oriented_sf, elastic.triclinic.TensorComponents
)
True
orientation_rotation_vti = (
orientation.DirectOrthonormalBasis.from_basis_vectors(
local_x=np.array([0, 1.0, 0]),
local_y=np.array([-1.0, 0, 0]),
local_z=np.array([0, 0, 1.0]),
)
)
to_solver_form(elastic_vti_material.with_orientation(orientation_rotation_vti))
<IPython.core.display.HTML object>
salvus.material.elastic.triclinic.TensorComponents
AzimuthDipRake
orientation. This material has different properties in three orthogonal
directions, and we can specify its orientation using the azimuth, dip, and
rake angles.# Completely fictitious material properties
orthotropic_material = elastic.orthotropic.EngineeringConstants.from_params(
rho=2500,
e1=50e9,
e2=30e9,
e3=20e9,
v12=0.2,
v13=0.1,
v23=0.3,
g12=10e9,
g13=5e9,
g23=2e9,
)
orthotropic_material
<IPython.core.display.HTML object>
salvus.material.elastic.orthotropic.EngineeringConstants
# Let's visualize the entries of the stiffness tensor as well:
orthotropic_material.to_tensor_components()
<IPython.core.display.HTML object>
salvus.material.elastic.orthotropic.TensorComponents
orientation_orthotropic_1 = orientation.AzimuthDipRake.from_params(
azimuth=0, dip=0, rake=90
)
orthotropic_material_oriented = orthotropic_material.with_orientation(
orientation_orthotropic_1
)
to_solver_form(orthotropic_material_oriented)
<IPython.core.display.HTML object>
salvus.material.elastic.triclinic.TensorComponents
elastic.orthotropic.EngineeringConstants.from_material(
to_solver_form(orthotropic_material_oriented),
reduction_method="remove-components",
)
<IPython.core.display.HTML object>
salvus.material.elastic.orthotropic.EngineeringConstants
orthotropic_material_oriented_45 = orthotropic_material.with_orientation(
orientation.AzimuthDipRake.from_params(azimuth=0, dip=0, rake=45)
)
to_solver_form(orthotropic_material_oriented_45)
<IPython.core.display.HTML object>
salvus.material.elastic.triclinic.TensorComponents
try:
elastic.orthotropic.EngineeringConstants.from_material(
to_solver_form(orthotropic_material_oriented_45),
reduction_method="remove-components",
)
except TypeError as e:
print(e)
Passed material of type <class 'salvus.material.elastic.triclinic.TensorComponents'> can't be treated as <class 'salvus.material.elastic.orthotropic.TensorComponents'>, as it does not respect the symmetry. The component C16 should be zero, but it is not.
elastic.orthotropic.EngineeringConstants.from_material(
to_solver_form(orthotropic_material_oriented_45), reduction_method="force"
)
<IPython.core.display.HTML object>
salvus.material.elastic.orthotropic.EngineeringConstants
orthotropic_material_oriented_dramatic = orthotropic_material.with_orientation(
orientation.AzimuthDipRake.from_params(azimuth=22.5, dip=30, rake=45)
)
to_solver_form(orthotropic_material_oriented_dramatic)
<IPython.core.display.HTML object>
salvus.material.elastic.triclinic.TensorComponents