from __future__ import annotations
from osaft import log
from osaft.core.basecomposite import BaseFrequencyComposite
from osaft.core.frequency import Frequency
from osaft.core.functions import sqrt
from osaft.core.variable import ActiveVariable, PassiveVariable
[docs]class RigidSolid(BaseFrequencyComposite):
"""RigidSolid class
:param frequency: excitation frequency in [Hz]
:param rho: density in [kg/m^3]
"""
def __init__(
self,
frequency: int | float | Frequency,
rho: float,
) -> None:
"""Constructor method"""
# Calling parent class
super().__init__(frequency)
# Independent variables
self._rho_s = PassiveVariable(rho, "density rho")
if type(self) is RigidSolid:
log.debug(f"Creating {self}")
def __repr__(self) -> str:
return f"RigidSolid(f={self.f}, rho={self.rho_s})"
# -------------------------------------------------------------------------
# Setters and Getters for Independent Variables
# -------------------------------------------------------------------------
@property
def rho_s(self) -> float:
"""Returns the density :math:`\\rho_{s}`.
:getter: returns the value for the density
:setter: automatically invokes
:meth:`osaft.core.variable.BaseVariable.notify`
"""
return self._rho_s.value
@rho_s.setter
def rho_s(self, value: float) -> None:
self._rho_s.value = value
[docs]class ElasticSolid(RigidSolid):
"""ElasticSolid class
:param frequency: excitation frequency in [Hz]
:param E: Young's modulus in [Pa]
:param nu: Poisson's ratio in [-]
:param rho: density in [km m^-3]
"""
def __init__(self, frequency, E, nu, rho) -> None:
"""Constructor method"""
super().__init__(frequency, rho)
# Independent variables
self._E_s = PassiveVariable(E, "Young's modulus E")
self._nu_s = PassiveVariable(nu, "Poisson's ratio nu")
# Dependent variables
self._c_l = ActiveVariable(self._compute_c_l, "primary wave speed c_l")
self._k_l = ActiveVariable(
self._compute_k_l,
"wavenumber of primary wave k_l",
)
self._c_t = ActiveVariable(
self._compute_c_t,
"secondary wave speed c_t",
)
self._k_t = ActiveVariable(
self._compute_k_t,
"wavenumber of secondary wave k_t",
)
self._G = ActiveVariable(self._compute_G, "shear modulus G")
self._lambda = ActiveVariable(
self._compute_lambda,
"second Lame parameter lambda",
)
self._B_s = ActiveVariable(self._compute_B_s, "bulk modulus B_s")
self._kappa_s = ActiveVariable(
self._compute_kappa_s,
"compressibility kappa_s",
)
# Dependencies
self._G.is_computed_by(self._E_s, self._nu_s)
self._lambda.is_computed_by(self._E_s, self._nu_s)
self._c_l.is_computed_by(self._E_s, self._nu_s, self._rho_s)
self._k_l.is_computed_by(self._c_l, self.frequency._omega)
self._c_t.is_computed_by(self._E_s, self._nu_s, self._rho_s)
self._k_t.is_computed_by(self._c_t, self.frequency._omega)
self._B_s.is_computed_by(self._E_s, self._nu_s)
self._kappa_s.is_computed_by(self._B_s)
# no if clause needed because last in inheritance diagram
log.debug(f"Creating {self}")
def __repr__(self) -> str:
return (
f"ElasticSolid(f={self.f}, rho={self.rho_s}, "
f"E={self.E_s}, nu={self.nu_s})"
)
# -------------------------------------------------------------------------
# Setters and Getters for Independent Variables
# -------------------------------------------------------------------------
@property
def E_s(self) -> float:
"""Returns the Young's modulus :math:`E_{s}` [Pa].
:getter: returns the value for the Young's modulus
:setter: automatically invokes
:meth:`osaft.core.variable.BaseVariable.notify`
"""
return self._E_s.value
@E_s.setter
def E_s(self, value: float) -> None:
self._E_s.value = value
@property
def nu_s(self) -> float:
"""Returns the Poisson's ratio :math:`\\nu_{s}`.
:getter: returns the value for the Poisson's ratio
:setter: automatically invokes
:meth:`osaft.core.variable.BaseVariable.notify`
"""
return self._nu_s.value
@nu_s.setter
def nu_s(self, value: float) -> None:
if not (0 <= value <= 0.5):
raise ValueError(
"The Poisson's ratio `nu` needs to be in the "
"range 0 <= nu <= 0.5",
)
self._nu_s.value = value
# -------------------------------------------------------------------------
# Getters for Dependent Variables
# -------------------------------------------------------------------------
@property
def G(self) -> float:
"""Returns the shear modulus :math:`G`."""
return self._G.value
@property
def B_s(self) -> float:
"""Returns the bulk modulus :math:`B_{s}` [Pa]"""
return self._B_s.value
@property
def kappa_s(self) -> float:
"""Returns the compressibility :math:`\\kappa_{s}` [1/Pa]"""
return self._kappa_s.value
@property
def c_l(self) -> float:
"""Returns the longitudinal wave speed :math:`c_l` [m/s]"""
return self._c_l.value
@property
def c_t(self) -> float:
"""Return the transverse wave speed :math:`c_t` [m/s]"""
return self._c_t.value
@property
def k_l(self) -> float:
"""Returns the longitudinal wave number :math:`k_l` [1/m]"""
return self._k_l.value
@property
def k_t(self) -> float:
"""Returns the transverse wave number :math:`k_t` [1/m]"""
return self._k_t.value
@property
def lame_1(self) -> float:
"""Returns the first Lamé parameter :math:`\\lambda` [Pa]"""
return self._lambda.value
@property
def lame_2(self) -> float:
"""Returns the second Lamé parameter :math:`\\mu`"""
return self.G
# -------------------------------------------------------------------------
# Dependent Variables Methods
# -------------------------------------------------------------------------
def _compute_G(self) -> float:
return self.G_from_E_nu(self.E_s, self.nu_s)
def _compute_lambda(self) -> float:
return self.lambda_from_E_nu(self.E_s, self.nu_s)
def _compute_B_s(self) -> float:
return self.E_s / (1 - 2 * self.nu_s) / 3
def _compute_kappa_s(self) -> float:
return 1 / self.B_s
def _compute_c_l(self) -> float:
return self.c1_from_E_nu(self.E_s, self.nu_s, self.rho_s)
def _compute_c_t(self) -> float:
return self.c2_from_E_nu(self.E_s, self.nu_s, self.rho_s)
def _compute_k_l(self) -> float:
return self.omega / self.c_l
def _compute_k_t(self) -> float:
return self.omega / self.c_t
# -------------------------------------------------------------------------
# Conversion Methods
# -------------------------------------------------------------------------
[docs] @staticmethod
def E_from_wave_speed(
c_1: float,
c_2: float,
rho: float,
) -> float:
"""Computes the Young's modulus :math:`E` from the primary and the
secondary wave speed :math:`c_1`, :math:`c_2` and the density
:math:`\\rho`.
:param c_1: primary wave speed [m/s]
:param c_2: secondary wave speed [m/s]
:param rho: density [kg/m^3]
"""
return (
rho
* c_2**2
* (3 * c_1**2 - 4 * c_2**2)
/ (c_1**2 - c_2**2)
)
[docs] @staticmethod
def nu_from_wave_speed(
c_1: float,
c_2: float,
) -> float:
"""Computes the Poisson's ratio :math:`\\nu` from the primary and the
secondary wave speed :math:`c_1`, :math:`c_2`, and the density
:math:`\\rho`.
:param c_1: primary wave speed [m/s]
:param c_2: secondary wave speed [m/s]
"""
return (1 - 2 * (c_2 / c_1) ** 2) / (2 - 2 * (c_2 / c_1) ** 2)
[docs] @staticmethod
def lambda_from_wave_speed(
c_1: float,
c_2: float,
rho: float,
) -> float:
"""Computes the Lamé first parameter :math:`\\lambda` from the
primary and the secondary wave speed :math:`c_1`, :math:`c_2` and the
density :math:`\\rho`.
:param c_1: primary wave speed [m/s]
:param c_2: secondary wave speed [m/s]
:param rho: density [kg/m^3]
"""
G = c_2**2 * rho
return c_1**2 * rho - 2 * G
[docs] @staticmethod
def G_from_wave_speed(
c_2: float,
rho: float,
) -> float:
"""Computes the second Lamé parameter :math:`G` from the secondary
wave speed :math:`c_2` and the density :math:`\\rho`.
:param c_2: secondary wave speed [m/s]
:param rho: density [kg/m^3]
"""
return c_2**2 * rho
[docs] @staticmethod
def c1_from_E_nu(
E: float,
nu: float,
rho: float,
) -> float:
"""Computes the primary wave speed :math:`c_1` from the Young's modulus
:math:`E` and the Poisson's ratio :math:`\\nu`, and the density
:math:`\\rho`.
:param E: Young;s modulus [Pa]
:param nu: Poisson's ratio [-]
:param rho: density [kg/m^3]
"""
return sqrt(E * (1 - nu) / (rho * (1 + nu) * (1 - 2 * nu)))
[docs] @staticmethod
def c2_from_E_nu(
E: float,
nu: float,
rho: float,
) -> float:
"""Computes the secondary wave speed :math:`c_2` from the Young's
modulus :math:`E` and the Poisson's ratio :math:`\\nu`, and the density
:math:`\\rho`.
:param E: Young;s modulus [Pa]
:param nu: Poisson's ratio [-]
:param rho: density [kg/m^3]
"""
return sqrt(E / (2 * (1 + nu) * rho))
[docs] @staticmethod
def c1_from_Lame(
lam: float,
G: float,
rho: float,
) -> float:
"""Computes the primary wave speed :math:`c_1` from the Lamé parameters
:math:`\\lambda`, :math:`G`, and the density
:math:`\\rho`.
:param lam: first Lamé parameter [Pa]
:param G: second Lamé parameter [Pa]
:param rho: density [kg/m^3]
"""
return sqrt((lam + 2 * G) / rho)
[docs] @staticmethod
def c2_from_Lame(
G: float,
rho: float,
) -> float:
"""Computes the secondary wave speed :math:`c_2` from the Lamé
parameters :math:`\\lambda`, :math:`G`, and the density :math:`\\rho`.
:param G: second Lamé parameter [Pa]
:param rho: density [kg/m^3]
"""
return sqrt(G / rho)
[docs] @staticmethod
def E_from_Lame(
lam: float,
G: float,
) -> float:
"""Computes the Young's modulus :math:`E` from the Lamé parameters
:math:`\\lambda`, :math:`G`
:param lam: first Lamé parameter [Pa]
:param G: second Lamé parameter [Pa]
"""
return G * (3 * lam + 2 * G) / (lam + G)
[docs] @staticmethod
def nu_from_Lame(
lam: float,
G: float,
) -> float:
"""Computes the the Poisson's ratio :math:`\\nu` from the Lamé
parameters :math:`\\lambda`, :math:`G`.
:param lam: first Lamé parameter [Pa]
:param G: second Lamé parameter [Pa]
"""
return lam / (2 * (lam + G))
[docs] @classmethod
def lambda_from_E_nu(cls, E: float, nu: float) -> float:
"""Computes the first Lamé parameters :math:`\\lambda` from the Young's
modulus :math:`E` and the Poisson's ratio :math:`\\nu`.
:param E: Young;s modulus [Pa]
:param nu: Poisson's ratio [-]
"""
G = cls.G_from_E_nu(E, nu)
return 2 * G * nu / (1 - 2 * nu)
[docs] @staticmethod
def G_from_E_nu(
E: float,
nu: float,
) -> float:
"""Computes the second Lamé parameters :math:`G` from the Young's
modulus :math:`E` and the Poisson's ratio :math:`\\nu`.
:param E: Young;s modulus [Pa]
:param nu: Poisson's ratio [-]
"""
return E / (2 * (1 + nu))
if __name__ == "__main__":
pass