Skip to main content

Getting started

This page takes you from installation to your first results in about ten minutes. No prior knowledge of the package is assumed and basic notions of vibration (mass, stiffness, damping, resonance) are enough.

TipThe main idea to remember

Every computation in StructuralVibration.jl follows the same four steps:

  1. Model – describe the structure (Sdof, Beam, Plate, FE matrices…)
  2. Problem – say what you want to compute (free response, forced response, FRF,…)
  3. Solve – call solve(prob) (optionally with a solver, e.g. solve(prob, Newmark()))
  4. Post-process – plot, compare, extract modal parameters, …

Once you have understood this pattern on a single-degree-of-freedom system, the rest of the package follows naturally.

1 Installation

julia> ]
pkg> add StructuralVibration, CairoMakie

CairoMakie.jl is optional but it activates the plotting functions of the package (bode_plot, stabilization_plot, …). Any other Makie backend (GLMakie.jl, WGLMakie.jl) works as well.

using StructuralVibration, CairoMakie

2 Step 1 – Define a model

We start with the simplest vibrating system: a mass \(m\) attached to a spring and a viscous damper. It is fully described by its mass, its natural frequency \(f_0\) and its damping ratio \(\xi\).

m  = 1.     # Mass (kg)
f0 = 10.    # Natural frequency (Hz)
ξ  = 0.02   # Damping ratio (2 %)

sdof = Sdof(m, f0, ξ)

3 Step 2 – Free response

Let us pull the mass away from its equilibrium position and release it. The problem gathers the model, the initial conditions [x₀, v₀] and the time vector.

t  = 0.:1e-3:2.
u0 = [1e-3, 0.]    # Initial displacement (m) and velocity (m/s)

prob_free = SdofFreeTimeProblem(sdof, u0, t)
x_free = solve(prob_free).u
sv_plot(t, x_free, xlabel = "Time (s)", ylabel = "Displacement (m)")

The system oscillates at (almost) \(f_0\) = 10 Hz and the amplitude decays because of damping. Try ξ = 0. or ξ = 1. to see an undamped and a critically damped system.

4 Step 3 – Forced response

Now, we excite the mass with a harmonic force \(F(t) = F_0 \sin(2\pi f t)\). Only the problem changes: the model and the call to solve stay the same.

F0 = 10.   # Force amplitude (N)
f  = 9.5   # Excitation frequency (Hz), close to resonance

prob_harmo = SdofHarmonicTimeProblem(sdof, u0, t, F0, f, :force)
x_harmo = solve(prob_harmo).u
sv_plot(t, x_harmo, xlabel = "Time (s)", ylabel = "Displacement (m)")

The response combines a decaying transient (free response) and a steady-state oscillation at the excitation frequency. Arbitrary excitations (impacts, sweeps, random noise) are handled by SdofForcedTimeProblem together with the signals described in Excitation models.

5 Step 4 – Frequency Response Function

Rather than computing one response per excitation frequency, we usually characterize a structure by its Frequency Response Function (FRF) \(H(f)\), the ratio between the displacement and the force at each frequency.

freq = 1.:0.05:30.

prob_frf = SdofFRFProblem(sdof, freq)
H = solve(prob_frf).u
bode_plot(freq, H, isdeg = true)

The resonance peak is located at \(f_0\) and its sharpness is governed by \(\xi\). The phase shifts by 180° when crossing the resonance.

6 Step 5 – Same pattern, real structure

The four steps remain the same for continuous structures. Here, we compute the FRFs of a simply supported steel beam from its modes, add measurement noise, and identify its natural frequencies back, as an experimentalist would.

# 1. Model - Simply supported beam
L, b, h = 1., 0.03, 0.01
beam = Beam(L, b*h, b*h^3/12, 2.1e11, 7850.)

fmax = 500.
ωn, kn = modefreq(beam, 2fmax)       # Natural frequencies and wavenumbers
xm, xe = [0.2, 0.7], [0.35]          # Measurement and excitation points
ms_m, ms_e = modeshape(beam, kn, xm), modeshape(beam, kn, xe)

# 2. Problem + 3. Solve - Accelerances by modal superposition
freq = 1.:0.25:fmax
ξn = 0.01
prob = ModalFRFProblem(ωn, ξ, freq, ms_m, ms_e)
H = solve(prob, type = :acc, progress = false).u

# 4. Post-process - Noisy "measurement" (SNR = 40 dB) + modal identification
H_meas = agwn(H, 40.)
poles = poles_extraction(EMAProblem(H_meas, freq, type_frf = :acc), 20, LSCF())
fn_id, ξn_id = poles2modal(poles)

We computed accelerances (acceleration/force) because this is what an accelerometer and an impact hammer actually measure.

fig = Figure()
ax = Axis(fig[1, 1], xlabel = "Frequency (Hz)", ylabel = "Accelerance (dB, ref: 1 m/s²/N)")
lines!(ax, freq, to_dB.(H_meas[1, 1, :]), label = "Noisy FRF")
lines!(ax, freq, to_dB.(H[1, 1, :]), label = "Exact FRF")
vlines!(ax, fn_id, color = :green, linestyle = :dash, label = "Identified modes")
xlims!(ax, freq[1], freq[end])
axislegend(ax, position = :rb)
fig
fn_exact = ωn[ωn .≤ 2π*fmax]/2π
println("Exact frequencies (Hz):      ", round.(fn_exact, digits = 2))
println("Identified frequencies (Hz): ", round.(fn_id, digits = 2))
println("Identified damping (%):      ", round.(100ξn_id, digits = 2))
Exact frequencies (Hz):      [23.45, 93.81, 211.08, 375.25]
Identified frequencies (Hz): [23.45, 93.82, 211.08, 375.27]
Identified damping (%):      [2.0, 1.99, 2.02, 2.0]

In twenty lines, we went from a structural model to synthetic measurements and back to modal parameters with a known ground truth. This round trip is what the package is designed for.

7 Where to go next?

I want to… Go to
Discover structural dynamics interactively Apps
Build a complete virtual test campaign From model to virtual measurement
Perform an experimental modal analysis Experimental modal analysis
Identify modes from responses only Operational modal analysis
Simulate a FE model in the time domain Choosing a time integration scheme
Estimate the noise level of a signal or denoise it Noise estimation and denoising
Display and animate mode shapes Visualizing and animating deflection shapes
Use my own matrices or measurements Using your own models and data
Look up a function or a type Models, Solvers, Signal processing