Modal utils

Utils for converting between modal and physical coordinates.

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.


source

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.

param mode_numbers: Array of mode numbers, representing different vibration modes. :param string_length: Total length of the string. :param grid: Grid of points to evaluate the modes on. :return: Matrix with the modal shapes as columns (shape: (grid.size, mode_numbers.size)).*
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
M = create_modal_matrix(np.arange(1, 51), grid=np.linspace(0, 1, 100))
assert M.shape == (100, 50)

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.


source

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.

param physical_displacement: Array of displacements at grid points. :param modal_shapes: Matrix of modal shapes (each column is a mode shape). :param string_length: Length of the string. :param num_gridpoints: Number of grid points along the string. :return: Array of amplitudes in the modal domain.*
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

source

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.

param modal_amplitudes: Array of amplitudes in the modal domain. :param modal_shapes: Matrix of modal shapes (each column is a mode shape). :param string_length: Length of the string. :return: Array of physical displacements at the grid points.*
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

source

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.

param modes: Array of mode numbers, representing different vibration modes. :param pluck_position: Position of the pluck on the string. :param initial_deflection: Initial displacement of the string at the pluck position. :param string_length: Total length of the string. :return: Array of Fourier-Sine coefficients for each mode.*
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
n_gridpoints = 100
dx  = 1 / n_gridpoints   # m spatial sampling interval
mu = np.arange(1, 50 + 1) # mode numbers
length = 1.0 # m
mode_numbers = np.arange(1, 50 + 1)
grid = np.arange(0, length, dx)

q = create_pluck_modal(
    mode_numbers,
    pluck_position=0.28,
    initial_deflection=0.03,
)

M = create_modal_matrix(
    mu, 
    length, 
    grid
)

u = to_displacement(q, M, length)
q = to_modal(u, M, length, n_gridpoints)
u0_new = to_displacement(q, M, length)
assert np.allclose(u, u0_new, atol=1e-5)