= create_modal_matrix(np.arange(1, 51), grid=np.linspace(0, 1, 100))
M assert M.shape == (100, 50)
Modal utils
The modal matrix $ ^{G K} $ represents the mode shapes of a system, with each column as a mode shape corresponding to a vibration mode. Wavenumbers $ ^K $ are given by $ k_= $ for modes $ $ in a system of length $ L $. The grid points $ ^G $ represent spatial discretization, with $ g_j = j x $.
The modal matrix is not a direct outer product of $ $ and $ $. Instead, it’s constructed by evaluating mode shapes at these grid points. For systems like vibrating strings, this often involves sinusoidal functions of $ k_$ and $ g_j $, but more complex systems may require detailed analysis or numerical methods.
create_modal_matrix
create_modal_matrix (mode_numbers:numpy.ndarray, string_length:float=1.0, grid:numpy.ndarray=None)
*Creates a matrix with the modal shapes as columns.
Type | Default | Details | |
---|---|---|---|
mode_numbers | ndarray | array of mode numbers (integers) | |
string_length | float | 1.0 | total length of the string in meters |
grid | ndarray | None | grid of points to evaluate the modes on |
Returns | ndarray |
To convert from the physical domain to the modal domain, we use the modal matrix \(\mathbf{M}\) and a scaling factor:
\[ \mathbf{u} = \frac{2}{l} \mathbf{M} \cdot \mathbf{q} \]
To convert from the modal domain to the physical domain, we use the inverse modal matrix \(\mathbf{M}^{-1}\) and a scaling factor. Since the modal matrix is orthogonal, the inverse is equal to the transpose:
\[ \mathbf{q} = \frac{l}{g} \mathbf{M}^T \cdot \mathbf{u} \]
where \(g\) is the number of grid points and \(l\) is the length of the string.
to_modal
to_modal (physical_displacement:numpy.ndarray, modal_shapes:numpy.ndarray, string_length:float=1.0, num_gridpoints:int=100)
*Convert physical displacement to modal amplitudes.
Type | Default | Details | |
---|---|---|---|
physical_displacement | ndarray | Displacement at grid points | |
modal_shapes | ndarray | Modal shapes (eigenvectors) | |
string_length | float | 1.0 | Length of the string in meters |
num_gridpoints | int | 100 | Number of grid points |
Returns | ndarray |
to_displacement
to_displacement (modal_amplitudes:numpy.ndarray, modal_shapes:numpy.ndarray, string_length:float=1.0)
*Convert modal amplitudes to physical displacement along the string.
Type | Default | Details | |
---|---|---|---|
modal_amplitudes | ndarray | Amplitudes in the modal domain | |
modal_shapes | ndarray | Modal shapes (eigenvectors) | |
string_length | float | 1.0 | Length of the string in meters |
Returns | ndarray |
create_pluck_modal
create_pluck_modal (mode_numbers:numpy.ndarray, pluck_position:float=0.28, initial_deflection:float=0.03, string_length:float=1.0)
*Calculate the Fourier-Sine coefficients of the initial deflection of a plucked string in modal coordinates.
Type | Default | Details | |
---|---|---|---|
mode_numbers | ndarray | array of mode numbers (integers) | |
pluck_position | float | 0.28 | position of pluck on the string in meters |
initial_deflection | float | 0.03 | initial deflection of the string in meters |
string_length | float | 1.0 | total length of the string in meters |
Returns | ndarray |
= 100
n_gridpoints = 1 / n_gridpoints # m spatial sampling interval
dx = np.arange(1, 50 + 1) # mode numbers
mu = 1.0 # m
length = np.arange(1, 50 + 1)
mode_numbers = np.arange(0, length, dx)
grid
= create_pluck_modal(
q
mode_numbers,=0.28,
pluck_position=0.03,
initial_deflection
)
= create_modal_matrix(
M
mu,
length,
grid
)
= to_displacement(q, M, length)
u = to_modal(u, M, length, n_gridpoints)
q = to_displacement(q, M, length)
u0_new assert np.allclose(u, u0_new, atol=1e-5)