/ proof-of-concept / cymsim_old
Sign in
proof-of-concept / cymsim_old
cymsim_old / src / cymsim / material.py
96 lines · 3.6 KBCodeBlameHistory
3688ceacymsim: Python port of cymbalsim with a modal linear model and a PyTorch von Karman modelJeremy Magland 1"""Materials: elastic constants, the loss factor of internal friction, and the
2thermal constants from which the thermoelastic damping follows."""
4from __future__ import annotations
6import math
7from dataclasses import dataclass
9from .constants import SPEED_OF_SOUND
12@dataclass(frozen=True)
13class Thermal:
14 """Thermal constants of a metal. All three are needed for Zener's thermoelastic damping."""
16 alpha: float
17 """Linear thermal expansion [1/K]."""
18 cp: float
19 """Specific heat [J/(kg K)]."""
20 k: float
21 """Thermal conductivity [W/(m K)]."""
23 def __post_init__(self) -> None:
24 if not (self.alpha >= 0 and self.cp >= 1 and self.k >= 1e-3):
25 raise ValueError("thermal constants must be positive (alpha >= 0, cp >= 1, k >= 1e-3)")
28@dataclass(frozen=True)
29class Material:
30 """A homogeneous isotropic metal.
32 The decay of the sound is not prescribed but derived from ``loss_factor``
33 (the hysteretic loss factor of the metal's internal friction, of order
34 1e-4 for bronze, steel and aluminum), from ``thermal`` (Zener's
35 thermoelastic damping; ``None`` leaves it out) and from the radiation of
36 the plate into the air, which the models compute from the geometry.
37 """
39 E: float
40 """Young's modulus [Pa]."""
41 nu: float
42 """Poisson ratio."""
43 rho: float
44 """Density [kg/m^3]."""
45 loss_factor: float = 0.0
46 """Loss factor eta of internal friction: a mode decays at the rate eta omega / 2."""
47 thermal: Thermal | None = None
48 """Thermal constants for the thermoelastic damping, or None for none."""
50 def __post_init__(self) -> None:
51 if not self.E >= 1e6:
52 raise ValueError("E must be at least 1e6 Pa")
53 if not 0 <= self.nu < 0.5:
54 raise ValueError("nu must lie in [0, 0.5)")
55 if not self.rho >= 1:
56 raise ValueError("rho must be at least 1 kg/m^3")
57 if not 0 <= self.loss_factor < 0.1:
58 raise ValueError("loss_factor must be small (metals have 1e-4 to 1e-3)")
60 def bending_stiffness(self, h):
61 """D = E h^3 / (12 (1 - nu^2)) [N m]; ``h`` may be an array."""
62 return self.E * h**3 / (12 * (1 - self.nu**2))
64 def membrane_stiffness(self, h):
65 """C = E h / (1 - nu^2) [N/m]."""
66 return self.E * h / (1 - self.nu**2)
68 def shear_stiffness(self, h):
69 """G = E h / (2 (1 + nu)) [N/m]."""
70 return self.E * h / (2 * (1 + self.nu))
72 @property
73 def in_plane_speed(self) -> float:
74 """Speed of in-plane waves, sqrt(E / (rho (1 - nu^2))) [m/s]; it sets the time step of the full model."""
75 return math.sqrt(self.E / (self.rho * (1 - self.nu**2)))
77 def bending_constant(self, h):
78 """kappa = sqrt(D / (rho h)) [m^2/s], so that omega = kappa k^2 for a bending wave."""
79 return (self.bending_stiffness(h) / (self.rho * h)) ** 0.5
81 def coincidence_frequency(self, h):
82 """Frequency at which the bending wavelength equals the wavelength of sound, c^2 / (2 pi kappa) [Hz]."""
83 return SPEED_OF_SOUND**2 / (2 * math.pi * self.bending_constant(h))
86STAINLESS_STEEL = Material(E=170e9, nu=0.29, rho=7900, loss_factor=3e-4, thermal=Thermal(17e-6, 500, 16))
87"""Stainless steel sheet."""
89MILD_STEEL = Material(E=200e9, nu=0.3, rho=7850, loss_factor=3e-4, thermal=Thermal(12e-6, 460, 50))
90"""Carbon steel sheet."""
92BRONZE = Material(E=110e9, nu=0.34, rho=8800, loss_factor=2e-4, thermal=Thermal(18e-6, 370, 40))
93"""Bell bronze, as used for cymbals."""
95ALUMINUM = Material(E=68.9e9, nu=0.33, rho=2700, loss_factor=1e-4, thermal=Thermal(23.6e-6, 896, 167))
96"""6061-T6 aluminum."""
↑↓ move↵openescclose