Universidade Federal do Rio Grande do Sul (UFRGS)
Programa de Pós-Graduação em Engenharia Civil (PPGEC)
1. Free vibration of undamped sdof systems
2. Energy dissipation
3. Free vibration of damped sdof systems
4. Damping ratio estimation
5. Assignment
Prof. Marcelo M. Rocha, Dr.techn. (ORCID)
Porto Alegre, RS, Brazil
# Importing Python modules required for this notebook
# (this cell must be executed with "shift+enter" before any other Python cell)
import numpy as np
import matplotlib.pyplot as plt
from MRPy import MRPy
The figure below shows an idealization of a single degree of freedom (sdof) mechanical system with its basic elements:
Although the idealization presented above may resemble some feasible device, the basic elements may also be seen as conceptual and represent a much broader concept. For instance, the restitutive force element could be the gravity acting upon a pendulum. Or the system response could also be a rotation angle instead of a displacement.
The dissipative force will be introduced in the next section and are initially disregarded. If we also disregard the external force, F(t)=0, any system response will be called free vibration and that is our first case for analysis.
By applying the equilibrium equation and accounting for the inertial force as stated by Newton's law gives:
m¨u+ku=0Applying Laplace transform over this equation gives:
L{m¨u+ku}=m[−su(0)−˙u(0)+s2ˉu(s)]+kˉu(s)=0Recognizing that u(0)=u0 is the system initial position and ˙u(0)=v0 is the system initial velocity and solving for ˉu(s) gives:
ˉu(s)=(ss2+ω2n)u0+(ωns2+ω2n)v0ωnwhere we have defined ω2n=k/m. The inverse transform is promptly recognized from the sine and cosine transforms previously presented:
u(t)=u0cosωnt+v0ωnsinωntIt can be seen that the free vibration occurs at the natural vibration frequency ωn, and the movement amplitude depends on the initial displacement and initial velocity.
Let us plot this function with some Python lines:
fn = 1.0 # natural vibration frequency (1 cycle per second = Hz)
wn = 2*np.pi*fn # conversion to rad/s
u0 = 1. # initial displacement of 1 meter
v0 = 5. # oscillation starts from rest (try changing this)
Td = 8. # time series duration (s)
fs = 32. # sampling rate (Hz), fs = 1/dt (dt is the time step)
t = np.linspace(0, Td, int(fs*Td))
u = u0*np.cos(wn*t) + (v0/wn)*np.sin(wn*t)
plt.figure(1, figsize=(8, 4), clear=True)
plt.plot(t, u)
plt.xlim( 0, Td); plt.xlabel('time (s)')
plt.ylim(-2, 2); plt.ylabel('u(t)')
plt.grid(True)
plt.show()
This is surely not an interesting result. Try changing the values for u0 and v0 to see what happens. Indeed, the solution above can also be given in the form:
u(t)=umaxcos(ωnt−θ)with:
umax=√u20+(v0ωn)2θ=arctan(v0u0ωn)The most important observation so far is the natural vibration frequency, that holds a sort of universal law for mechanical vibrations:
ωn=√kmHence, the larger the system stiffness the higher the frequency, while the larger the system mass the lower the frequency, and vice-versa. This special frequency can be also obtained by energy conservation, if one recognizes that there are two kinds of energy present in the system:
Assuming that if the maximum displacement of the system is umax, then the maximum velocity will be ωnumax. When the displacement attains its maximum the potential energy is maximum and the kinectic energy is minimun, and vice-versa. By energy conservation:
ku2max2=mω2nu2max2what leads to the equation for ωn.
The natural frequency is also expressed in cycles per second, or Hertz, related to the frequency in radians per second with:
fn=ωn2πAlternatively, the natural period of vibration:
Tn=1fn=2πωncan be used. These relations are illustrated in the figure below.
Besides the potential and kinectic energy, there is always some energy dissipation mechanism taking place during the system vibration (otherwise a perpetual motion would be possible). The most common causes for this dissipation are:
among others.
Each one of these phenomena must be properly modelled to enter the equilibrium equation, but the most common approach is to use the so-called newtonian or viscous damping model for the dissipative force, c˙u, where c is the viscous damping constant. The great advantage of this model is that the equilibrium equation preserves its linearity and solution easiness, but one must keep in mind that it is only a model and the definition of constant c may be quite challenging.
Most commonly the damping constant is presented as a ratio to critical damping, ζ, defined as:
ζ=c2mωnwhich is non-dimensional and for this reason more easily quantified. It can be shown that ζ=1 is the smallest damping prenventing the system from having a single oscillation (one can have an idea of this condition by releasing a pendulum under water).
The Chapter 9 of the Brazilian Code NBR6123-Forças devidas o vento nas edificações brings a table (Tabela 2) of suggested values for ζ according to the type of structural system undergoing wind induced vibration:
Structure type | ζ |
---|---|
Reinforced concrete buildings without stiffning walls | 0.020 |
Reinforced concrete buildings with stiffning walls | 0.015 |
Reinforced concrete towers and chimneys, tappered | 0.015 |
Reinforced concrete towers and chimneys, constant section | 0.010 |
Moment resisting steel buildings with welded connections | 0.010 |
Steel towers and chimneys, constant section | 0.008 |
Timber structures | 0.030 |
It can be observed that for Civil Engineering the range of values are not too wide, and a typical value ζ=0.01=1% is usually assumed when no further information is available.
In the next section it will be shown that despite of all uncertainty about energy dissipation, it is of utmost importance for the safety and good performance of mechanical systems.
Assuming now the viscous model for energy dissipation gives the free vibration equilibrium:
m¨u+c˙u+ku=0Applying Laplace transform over this equation gives:
L{m¨u+c˙u+ku}=m[−su(0)−˙u(0)+s2ˉu(s)]+c[−u(0)+sˉu(s)]+kˉu(s)=0Solving for ˉu(s) results in:
ˉu(s)=[(s+η)(s+η)2+ω2D]u0+[ωD(s+η)2+ω2D](v0+ηu0ωD)where we have additionally defined:
ω2D=ω2n−η2=ω2n(1−ζ2)η=c2m=ζωnThe inverse transform can be obtained with the well known sine and cosine transforms and the translation theorem in frequency domain:
u(t)=e−ζωnt[u0cosωDt+(v0+ζωnu0ωD)sinωDt]It can be seen that the free vibration now occurs at the natural damped vibration frequency ωD, and the movement amplitude depends on the initial displacement and initial velocity.
Although the natural frequency has changed, by recalling that the damping ration ζ usually is in the order of 1% implies, for instance, that:
ωD=ωn√1−0.012≈0.99995ωn≈ωnwhat means that, beyond the whole uncertainty about the actual damping, for usual damping values the natural frequency change may be disregarded.
Let us take a look at the free vibration damped response using the same time discretization from the previous example.
fn = 1.0 # natural vibration frequency (1 cycle per second = Hz)
wn = 2*np.pi*fn # conversion to rad/s
zt = 0.05 # damping ratio of 3% of the critical (try changing this)
u0 = 5. # initial displacement of 1 meter
v0 = 0. # oscillation starts from rest
Td = 8. # time series duration (s)
fs = 32. # sampling rate (Hz), fs = 1/dt (dt is the time step)
t = np.linspace(0, Td, int(fs*Td))
wD = wn*np.sqrt(1 - zt**2)
e = np.exp(-zt*wn*t)
uD = e*(u0*np.cos(wD*t) + ((v0 + zt*wn*u0)/wD)*np.sin(wD*t))
plt.figure(2, figsize=(8, 4), clear=True)
plt.plot(t, uD)
plt.plot(t, u0*e, 'r:', t, -u0*e, 'r:')
plt.xlim( 0, Td); plt.xlabel('time (s)')
plt.ylim(-10, 10); plt.ylabel('u(t)')
plt.grid(True)
It can be observed that the exponential envelope causes the undamped response to have its amplitude decreased along time. Try changing the damping ratio in the script above to see how this affect the response (but it must always be within the range 0<ζ<1).
As we did for the undamped response, the damped response in free vibration can be put in the form:
u(t)=umaxe−ζωntcos(ωDt−θ)with:
umax=√u20+(v0+ζωnu0ωD)2θ=arctan(v0+ζωnu0ωDu0)Now we calculate the amplitude ratio at two time instants where the cosine function reaches its maximum, which are N vibration cycles apart, what gives:
u(t)u(t+NTn)=exp[−ζωnt]exp[−ζωn(t+NTn)]=exp(−ζωnNTn)=exp(−2πζN)
Making u(t)=ui, u(t+NTn)=ui+N, taking natural logarithms and isolating ζ finally gives:
ζ=log(ui/ui+N)2πNThis formula is exemplified in the figure below with the output of a real accelerometer. It is important to emphasize that the estimator presented above is valid no matter which kinemactic parameter is used for the amplitude ratio (displacement, velocity or acceleration), for they are related by a constant that will cancel upon division.
Applying the formula gives:
ζ=ln(0.52/0.31)2π⋅8≈1%A usefull rule for estimating ζ without much effort is to count the number of cycles necessary for the amplitude to be reduced to half. In this case:
ζ=ln(2/1)2πN≈19NThe MRPy
module provides a more sophisticated tool for estimating all
parameters of a free damped response function available as a time series.
This is exemplifyed below using the same the u(t) function from the previous example.
fn = 2.0 # natural vibration frequency (1 cycle per second = Hz)
wn = 2*np.pi*fn # conversion to rad/s
zt = 0.03 # damping ratio of 1% of the critical (try changing this)
u0 = 5. # initial displacement of 1 meter
v0 = 0. # oscillation starts from rest
Td = 8. # time series duration (s)
fs = 64. # sampling rate (Hz), fs = 1/dt (dt is the time step)
t = np.linspace(0, Td, int(fs*Td))
wD = wn*np.sqrt(1 - zt**2)
e = np.exp(-zt*wn*t)
uD = e*(u0*np.cos(wD*t) + ((v0 + zt*wn*u0)/wD)*np.sin(wD*t) + 0.2*u0*np.cos(0.7*wD*t))
plt.figure(2, figsize=(8, 4), clear=True)
plt.plot(t, uD)
plt.plot(t, u0*e, 'r:', t, -u0*e, 'r:')
plt.xlim( 0, Td); plt.xlabel('time (s)')
plt.ylim(-10, 10); plt.ylabel('u(t)')
plt.grid(True)
print(type(uD), '\t', uD.shape, '\n')
uD = MRPy(uD, fs=fs) # converting numpy to MRPy object
uD.printAttrib()
<class 'numpy.ndarray'> (512,) fs = 64.0Hz Td = 8.0s NX = 1 N = 512 M = 257
ufit, p = uD.fit_decay() # calls fit_decay() method
t = uD.t_axis() # prepare time axis for plotting
plt.figure(3, figsize=(12, 6), clear=True)
plt.plot(t, uD[0])
plt.plot(t, ufit[0], 'r:')
plt.legend(('original','fitted'))
plt.xlim( 0, Td); plt.xlabel('time (s)')
plt.ylim(-10, 10); plt.ylabel('u(t)')
plt.grid(True)
# Print out fitted parameters
print('Amplitude: {0:4.2f}m '.format(p[0,0]))
print('Frequency: {0:4.2f}Hz '.format(p[0,1]))
print('Damping ratio: {0:4.2f}% '.format(p[0,2]*100))
print('Phase: {0:4.2f}rad'.format(p[0,3]))
Amplitude: 5.16m Frequency: 2.01Hz Damping ratio: 3.12% Phase: 0.12rad
The fitting result is usually not so accurate when the original function comes from
real measurements. In some cases the fitting algorithm (which uses scipy
module)
may even fail in presenting any usefull result.
%matplotlib inline
data = MRPy.from_file('resources/data/iNVH001', form='invh')
data.printAttrib()
data.plot_time(fig=1);
fs = 99.7Hz Td = 23.0s NX = 3 N = 2296 M = 1149
free = data.extract((2.5, 5.5), by='time')
free.printAttrib()
free.plot_time(fig=2);
fs = 99.7Hz Td = 3.0s NX = 3 N = 298 M = 150
afit, par = free.fit_decay()
t = free.t_axis() # prepare time axis for plotting
plt.figure(4, figsize=(12, 6), clear=True)
plt.plot(t, free[2])
plt.plot(t, afit[2], 'r:')
plt.legend(('original','fitted'))
plt.xlim( 0, 3); plt.xlabel('time (s)')
plt.ylim(-3, 3); plt.ylabel('u(t)')
plt.grid(True)
print('Amplitude: {0:4.2f}m/s2'.format(par[2,0]))
print('Frequency: {0:4.2f}Hz '.format(par[2,1]))
print('Damping ratio: {0:4.2f}% '.format(par[2,2]*100))
print('Phase: {0:4.2f}rad '.format(par[2,3]))
Amplitude: 2.10m/s2 Frequency: 8.34Hz Damping ratio: 1.25% Phase: -0.89rad
MRPy.fit_decay()
.Prazo: 30 de março de 2022.
dados = MRPy.from_file("teste", form='excel')
print(dados)
[[23. 25. 18. 22. 34. 30. 21. 25. 22. 29.]]
dados.printAttrib()
fs = 1.1Hz Td = 9.0s NX = 1 N = 10 M = 6
dados.plot_time()
[[<matplotlib.lines.Line2D at 0x1b8b588bb80>]]