Source code for osaft.core.solids

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