Modal (vibration)
fpc.modal
modal.py - classical vibration and modal analysis.
Vibration analysis predicts how structures and machines oscillate. These helpers cover the single-degree-of-freedom (SDOF) spring-mass-damper - the building block of all vibration theory - plus a multi-DOF eigenvalue solver that finds natural frequencies and mode shapes using numpy's linear algebra.
It also pairs two SciPy workhorses: solve_ivp to SIMULATE a damped
oscillator's ring-down, and curve_fit to do the inverse - recover the
natural frequency and damping ratio FROM measured response data.
Modal
Vibration and modal-analysis calculations.
Source code in fpc/modal.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
natural_frequency(*, stiffness, mass)
Undamped natural frequency of an SDOF system.
Returns both the angular frequency omega_n = sqrt(k/m) [rad/s] and the ordinary frequency f_n = omega_n / (2*pi) [Hz], because engineers quote both.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stiffness
|
spring stiffness k [N/m] |
required | |
mass
|
mass m [kg] |
required |
Returns:
| Type | Description |
|---|---|
|
tuple (omega_n [rad/s], f_n [Hz]) |
Source code in fpc/modal.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
damping_ratio(*, damping, mass, stiffness)
Dimensionless damping ratio zeta = c / (2sqrt(km)).
zeta < 1 underdamped (oscillates), = 1 critically damped, > 1 overdamped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
damping
|
viscous damping coefficient c [N*s/m] |
required | |
mass
|
mass m [kg] |
required | |
stiffness
|
stiffness k [N/m] |
required |
Returns:
| Type | Description |
|---|---|
|
damping ratio zeta [-] |
Source code in fpc/modal.py
41 42 43 44 45 46 47 48 49 50 51 52 | |
damped_natural_frequency(*, stiffness, mass, damping)
Damped natural frequency omega_d = omega_n * sqrt(1 - zeta^2).
This is the frequency a real (lightly damped) system actually rings at.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stiffness
|
stiffness k [N/m] |
required | |
mass
|
mass m [kg] |
required | |
damping
|
damping coefficient c [N*s/m] |
required |
Returns:
| Type | Description |
|---|---|
|
damped angular frequency [rad/s] |
Source code in fpc/modal.py
54 55 56 57 58 59 60 61 62 63 64 65 66 | |
mode_shapes(*, mass_matrix, stiffness_matrix)
Natural frequencies and mode shapes of a multi-DOF system.
Solves the generalized eigenvalue problem Kphi = omega^2 * Mphi. Each eigenvalue is omega^2; each eigenvector is a mode shape describing the relative motion of every degree of freedom at that frequency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mass_matrix
|
mass matrix M, shape (n, n) [kg] |
required | |
stiffness_matrix
|
stiffness matrix K, shape (n, n) [N/m] |
required |
Returns:
| Type | Description |
|---|---|
|
tuple (natural_frequencies [Hz] sorted ascending, mode_shapes as columns of an array) |
Source code in fpc/modal.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
simulate_free_vibration(*, mass, stiffness, damping, initial_displacement, initial_velocity=0.0, duration, num_points=500)
Simulate the free ring-down of an SDOF spring-mass-damper.
Integrates mx'' + cx' + k*x = 0 with scipy.integrate.solve_ivp.
We rewrite the second-order equation as two first-order ones using the
state [x, v] (position and velocity), which is the standard trick for
feeding any ODE to a numerical solver.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mass
|
mass m [kg] |
required | |
stiffness
|
stiffness k [N/m] |
required | |
damping
|
damping coefficient c [N*s/m] |
required | |
initial_displacement
|
starting position x(0) [m] |
required | |
initial_velocity
|
starting velocity x'(0) [m/s], defaults to 0 |
0.0
|
|
duration
|
how long to simulate [s] |
required | |
num_points
|
number of evenly spaced output samples |
500
|
Returns:
| Type | Description |
|---|---|
|
tuple of numpy arrays (time [s], displacement [m]) |
Source code in fpc/modal.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
fit_damped_response(*, time, displacement, guess_frequency_hz=1.0)
Recover natural frequency and damping ratio from measured ring-down.
Given (time, displacement) samples of a decaying oscillation - say from an accelerometer - fit the underdamped free-vibration model
x(t) = A * exp(-zeta*omega_n*t) * cos(omega_d*t + phi)
where omega_d = omega_n*sqrt(1 - zeta^2). scipy.optimize.curve_fit
adjusts the four parameters (A, zeta, omega_n, phi) to best match the
data. This is the inverse of :meth:simulate_free_vibration, so feeding
it that method's output should return the parameters you started with.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
time
|
sample times [s] (1-D array-like) |
required | |
displacement
|
measured displacement at each time [m] |
required | |
guess_frequency_hz
|
rough starting guess for the frequency [Hz], which helps curve_fit converge |
1.0
|
Returns:
| Type | Description |
|---|---|
|
dict with |
Source code in fpc/modal.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |