### ===================================================================================================================
### Tools for wave speed calculations
### ===================================================================================================================
# Copyright ©2025 Haskoning Nederland B.V.
### ===================================================================================================================
### 1. Import modules
### ===================================================================================================================
# General imports
import math
from warnings import warn
### ===================================================================================================================
### 2. Function for calculating the wave speed
### ===================================================================================================================
[docs]
def calculate_wave_speed(E: float, nu: float, density: float) -> float:
"""
Calculate the wave speed in a material using dynamics. `[1] <https://tinyurl.com/yn5zk4zu>`__
Inout:
- E (float): Young's modulus of the material, in [N/m2].
- nu (float): Poisson's ratio of the material, in [-].
- density (float): Density of the material, in [kg/m3].
Output:
- Returns the calculated wave speed as float, in [m/s].
"""
warn(
"WARNING:The Dynamics module is currently under active development. Functionality may change in future "
"updates, and formal validation is still pending. Please verify your results carefully before using "
"them in your applications.")
return math.sqrt(E / (density * (1 - nu**2)))
### ===================================================================================================================
### 3. Function for calculating the wavelength
### ===================================================================================================================
[docs]
def calculate_wavelength(E: float, nu: float, density: float, frequency: float) -> float:
"""
Calculate the length speed based on Young's modulus (E), Poisson's ratio (nu), density, and frequency.
Input:
- E (float): Young's modulus of the material, in [N/m2].
- nu (float): Poisson's ratio of the material, in [-].
- density (float): Density of the material, in [kg/m3].
- frequency (float): Frequency of the wave, in [Hz].
Output:
- Returns the calculated wavelength as float, in [m].
"""
warn(
"WARNING:The Dynamics module is currently under active development. Functionality may change in future "
"updates, and formal validation is still pending. Please verify your results carefully before using "
"them in your applications.")
wave_speed = calculate_wave_speed(E, nu, density)
return wave_speed / frequency
### ===================================================================================================================
### 4. Function for max mesh element size
### ===================================================================================================================
[docs]
def calculate_minimum_divisions(
geometry_complexity: float, material_property: float, physics_factor: float, accuracy_requirement: float,
computational_resource: float) -> int:
"""
Helper function to calculate the minimum number of divisions based on various factors, which can be used for the
max_mesh_element_size function. Factors should be larger than zero.
Input:
- geometry_complexity (float): A factor representing the complexity of the geometry.
- material_property (float): A factor representing the material properties.
- physics_factor (float): A factor representing the physics of the problem.
- accuracy_requirement (float): A factor representing the accuracy requirements.
- computational_resource (float): A factor representing the available computational resources.
Output:
- Returns the calculated minimum number of divisions as integer.
"""
warn(
"WARNING:The Dynamics module is currently under active development. Functionality may change in future "
"updates, and formal validation is still pending. Please verify your results carefully before using "
"them in your applications.")
if any([item <= 0 for item in
[geometry_complexity, material_property, physics_factor, accuracy_requirement, computational_resource]]):
raise ValueError("ERROR: The factors that define the minimum number of divisions must be larger than zero.")
minimum_divisions = int(
geometry_complexity * material_property * physics_factor * accuracy_requirement / computational_resource)
return max(minimum_divisions, 1) # Ensure at least one division
[docs]
def calculate_maximum_mesh_element_size(
E: float, nu: float, density: float, frequency: float, minimum_divisions: int = 8) -> float:
"""
Calculate the maximum mesh element size based on material properties, frequency, and minimal number of divisions.
Input:
- E (float): Young's modulus of the material, in [N/m2].
- nu (float): Poisson's ratio of the material, in [-].
- density (float): Density of the material, in [kg/m3].
- frequency (float): Frequency of the wave, in [Hz].
- minimum_divisions (int): Minimal number of divisions per wavelength (no units). Default value is 8. For more
detailed analysis use the calculate_minimum_divisions function.
Output:
- Returns the maximum mesh-element size as float, in [m].
"""
warn(
"WARNING:The Dynamics module is currently under active development. Functionality may change in future "
"updates, and formal validation is still pending. Please verify your results carefully before using "
"them in your applications.")
if minimum_divisions <= 0:
raise ValueError("ERROR: The minimum number of divisions should be a positive integer larger than zero.")
wave_speed = calculate_wave_speed(E=E, nu=nu, density=density)
wavelength = wave_speed / frequency
return wavelength / minimum_divisions
### ===================================================================================================================
### 5. End of script
### ===================================================================================================================