Path: blob/main/latex-templates/templates/mechanical-engineering/vibration_analysis.tex
51 views
unlisted
\documentclass[11pt,a4paper]{article}12% Document Setup3\usepackage[utf8]{inputenc}4\usepackage[T1]{fontenc}5\usepackage{lmodern}6\usepackage[margin=1in]{geometry}7\usepackage{amsmath,amssymb}8\usepackage{siunitx}9\usepackage{booktabs}10\usepackage{float}11\usepackage{caption}12\usepackage{hyperref}1314% PythonTeX Setup15\usepackage[makestderr]{pythontex}1617\title{Vibration Analysis: SDOF Systems and Modal Analysis}18\author{Mechanical Engineering Laboratory}19\date{\today}2021\begin{document}22\maketitle2324\begin{abstract}25This report presents computational analysis of mechanical vibrations including free and forced response of single degree of freedom (SDOF) systems, damping effects, frequency response, and modal analysis. Python-based computations provide quantitative analysis with dynamic visualization.26\end{abstract}2728\tableofcontents29\newpage3031\section{Introduction to Mechanical Vibrations}3233Vibration analysis is essential for:34\begin{itemize}35\item Machine design and reliability36\item Structural dynamics and earthquake engineering37\item Noise and vibration control38\item Condition monitoring and diagnostics39\end{itemize}4041% Initialize Python environment42\begin{pycode}43import numpy as np44import matplotlib.pyplot as plt45from scipy.integrate import odeint46from scipy.signal import lti, step, bode4748plt.rcParams['figure.figsize'] = (8, 5)49plt.rcParams['font.size'] = 1050plt.rcParams['text.usetex'] = True5152def save_fig(filename):53plt.savefig(filename, dpi=150, bbox_inches='tight')54plt.close()55\end{pycode}5657\section{SDOF System Fundamentals}5859\subsection{Equation of Motion}6061For a mass-spring-damper system:62\begin{equation}63m\ddot{x} + c\dot{x} + kx = F(t)64\end{equation}6566Natural frequency and damping ratio:67\begin{equation}68\omega_n = \sqrt{\frac{k}{m}}, \quad \zeta = \frac{c}{2\sqrt{km}} = \frac{c}{2m\omega_n}69\end{equation}7071\begin{pycode}72# SDOF system parameters73m = 1.0 # kg74k = 100 # N/m75c = 4.0 # Ns/m7677omega_n = np.sqrt(k/m)78zeta = c / (2*np.sqrt(k*m))79omega_d = omega_n * np.sqrt(1 - zeta**2)80f_n = omega_n / (2*np.pi)8182# Free vibration response83def free_vibration(y, t, m, c, k):84x, v = y85return [v, (-c*v - k*x)/m]8687t = np.linspace(0, 5, 1000)88y0 = [0.1, 0] # Initial displacement, zero velocity89sol = odeint(free_vibration, y0, t, args=(m, c, k))9091# Analytical solution for underdamped92x_analytical = y0[0] * np.exp(-zeta*omega_n*t) * \93(np.cos(omega_d*t) + zeta*omega_n/omega_d * np.sin(omega_d*t))9495fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))9697# Time response98ax1.plot(t, sol[:, 0]*1000, 'b-', linewidth=2, label='Numerical')99ax1.plot(t, x_analytical*1000, 'r--', linewidth=1, label='Analytical')100ax1.plot(t, y0[0]*1000*np.exp(-zeta*omega_n*t), 'k--', linewidth=1, alpha=0.5, label='Envelope')101ax1.plot(t, -y0[0]*1000*np.exp(-zeta*omega_n*t), 'k--', linewidth=1, alpha=0.5)102ax1.set_xlabel('Time (s)')103ax1.set_ylabel('Displacement (mm)')104ax1.set_title('Free Vibration Response')105ax1.legend()106ax1.grid(True, alpha=0.3)107108# Phase portrait109ax2.plot(sol[:, 0]*1000, sol[:, 1]*1000, 'b-', linewidth=1)110ax2.plot(sol[0, 0]*1000, sol[0, 1]*1000, 'go', markersize=10, label='Start')111ax2.plot(sol[-1, 0]*1000, sol[-1, 1]*1000, 'ro', markersize=10, label='End')112ax2.set_xlabel('Displacement (mm)')113ax2.set_ylabel('Velocity (mm/s)')114ax2.set_title('Phase Portrait')115ax2.legend()116ax2.grid(True, alpha=0.3)117118plt.tight_layout()119save_fig('free_vibration.pdf')120\end{pycode}121122\begin{figure}[H]123\centering124\includegraphics[width=\textwidth]{free_vibration.pdf}125\caption{Free vibration: time response with envelope decay and phase portrait.}126\end{figure}127128\begin{table}[H]129\centering130\caption{SDOF System Parameters}131\begin{tabular}{lcc}132\toprule133Parameter & Value & Units \\134\midrule135Natural frequency $\omega_n$ & \py{f"{omega_n:.2f}"} & rad/s \\136Natural frequency $f_n$ & \py{f"{f_n:.2f}"} & Hz \\137Damping ratio $\zeta$ & \py{f"{zeta:.3f}"} & -- \\138Damped frequency $\omega_d$ & \py{f"{omega_d:.2f}"} & rad/s \\139\bottomrule140\end{tabular}141\end{table}142143\section{Effect of Damping}144145\begin{pycode}146# Effect of damping ratio on response147zeta_values = [0.05, 0.1, 0.2, 0.5, 1.0, 2.0]148colors = plt.cm.viridis(np.linspace(0, 1, len(zeta_values)))149150fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))151152for zeta_i, color in zip(zeta_values, colors):153c_i = 2*zeta_i*np.sqrt(k*m)154sol_i = odeint(free_vibration, y0, t, args=(m, c_i, k))155ax1.plot(t, sol_i[:, 0]*1000, color=color, linewidth=1.5, label=f'$\\zeta$ = {zeta_i}')156157ax1.set_xlabel('Time (s)')158ax1.set_ylabel('Displacement (mm)')159ax1.set_title('Effect of Damping on Free Response')160ax1.legend(fontsize=8)161ax1.grid(True, alpha=0.3)162163# Logarithmic decrement164# For underdamped systems165delta = 2*np.pi*zeta / np.sqrt(1 - zeta**2) if zeta < 1 else 0166167# Peak amplitudes for calculating log decrement168peaks_idx = []169for i in range(1, len(sol)-1):170if sol[i, 0] > sol[i-1, 0] and sol[i, 0] > sol[i+1, 0]:171peaks_idx.append(i)172173if len(peaks_idx) >= 2:174x1 = sol[peaks_idx[0], 0]175x2 = sol[peaks_idx[1], 0]176delta_measured = np.log(x1/x2)177zeta_measured = delta_measured / np.sqrt(4*np.pi**2 + delta_measured**2)178else:179delta_measured = 0180zeta_measured = 0181182# Show peak decay183ax2.semilogy(t[peaks_idx], np.abs(sol[peaks_idx, 0])*1000, 'ro-', linewidth=2, markersize=8)184ax2.set_xlabel('Time (s)')185ax2.set_ylabel('Peak Amplitude (mm)')186ax2.set_title(f'Logarithmic Decrement: $\\delta$ = {delta_measured:.3f}')187ax2.grid(True, alpha=0.3)188189plt.tight_layout()190save_fig('damping_effect.pdf')191\end{pycode}192193\begin{figure}[H]194\centering195\includegraphics[width=\textwidth]{damping_effect.pdf}196\caption{Effect of damping ratio on free vibration and logarithmic decrement measurement.}197\end{figure}198199\section{Forced Vibration Response}200201\subsection{Harmonic Excitation}202203For $F(t) = F_0\sin(\omega t)$, the steady-state response is:204\begin{equation}205X = \frac{F_0/k}{\sqrt{(1-r^2)^2 + (2\zeta r)^2}}, \quad r = \frac{\omega}{\omega_n}206\end{equation}207208\begin{pycode}209# Frequency response function210r = np.linspace(0.01, 3, 500) # Frequency ratio211zeta_values = [0.05, 0.1, 0.2, 0.5, 0.7, 1.0]212213fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))214215# Magnitude216for zeta_i in zeta_values:217X_ratio = 1 / np.sqrt((1 - r**2)**2 + (2*zeta_i*r)**2)218ax1.plot(r, X_ratio, linewidth=1.5, label=f'$\\zeta$ = {zeta_i}')219220ax1.axvline(1, color='k', linestyle='--', alpha=0.5)221ax1.set_xlabel('Frequency Ratio $r = \\omega/\\omega_n$')222ax1.set_ylabel('Amplitude Ratio $X/(F_0/k)$')223ax1.set_title('Frequency Response - Magnitude')224ax1.legend(fontsize=8)225ax1.grid(True, alpha=0.3)226ax1.set_xlim(0, 3)227ax1.set_ylim(0, 10)228229# Phase230for zeta_i in zeta_values:231phi = np.arctan2(2*zeta_i*r, 1 - r**2)232ax2.plot(r, np.degrees(phi), linewidth=1.5, label=f'$\\zeta$ = {zeta_i}')233234ax2.axvline(1, color='k', linestyle='--', alpha=0.5)235ax2.axhline(90, color='k', linestyle=':', alpha=0.5)236ax2.set_xlabel('Frequency Ratio $r = \\omega/\\omega_n$')237ax2.set_ylabel('Phase Angle (degrees)')238ax2.set_title('Frequency Response - Phase')239ax2.legend(fontsize=8)240ax2.grid(True, alpha=0.3)241242plt.tight_layout()243save_fig('frequency_response.pdf')244\end{pycode}245246\begin{figure}[H]247\centering248\includegraphics[width=\textwidth]{frequency_response.pdf}249\caption{Frequency response function showing magnitude and phase for various damping ratios.}250\end{figure}251252\subsection{Resonance Analysis}253254\begin{pycode}255# Resonance characteristics256# Peak frequency and amplitude for underdamped systems257zeta_range = np.linspace(0.01, 0.7, 100)258r_peak = np.sqrt(1 - 2*zeta_range**2)259Q_factor = 1 / (2*zeta_range) # Quality factor260261# Maximum amplitude ratio at resonance262X_peak = 1 / (2*zeta_range*np.sqrt(1 - zeta_range**2))263264fig, axes = plt.subplots(2, 2, figsize=(12, 10))265266# Peak frequency ratio267axes[0, 0].plot(zeta_range, r_peak, 'b-', linewidth=2)268axes[0, 0].set_xlabel('Damping Ratio $\\zeta$')269axes[0, 0].set_ylabel('Peak Frequency Ratio $r_{peak}$')270axes[0, 0].set_title('Resonance Peak Location')271axes[0, 0].grid(True, alpha=0.3)272273# Quality factor274axes[0, 1].semilogy(zeta_range, Q_factor, 'r-', linewidth=2)275axes[0, 1].set_xlabel('Damping Ratio $\\zeta$')276axes[0, 1].set_ylabel('Quality Factor $Q$')277axes[0, 1].set_title('Quality Factor vs Damping')278axes[0, 1].grid(True, alpha=0.3)279280# Half-power bandwidth281bandwidth = 2*zeta_range282axes[1, 0].plot(zeta_range, bandwidth, 'g-', linewidth=2)283axes[1, 0].set_xlabel('Damping Ratio $\\zeta$')284axes[1, 0].set_ylabel('Half-Power Bandwidth $\\Delta r$')285axes[1, 0].set_title('Half-Power Bandwidth')286axes[1, 0].grid(True, alpha=0.3)287288# Time domain at resonance289omega_f = omega_n # Forcing at natural frequency290t_res = np.linspace(0, 10, 2000)291292def forced_vibration(y, t, m, c, k, F0, omega):293x, v = y294F = F0 * np.sin(omega * t)295return [v, (F - c*v - k*x)/m]296297F0 = 10 # N298sol_res = odeint(forced_vibration, [0, 0], t_res, args=(m, c, k, F0, omega_f))299300axes[1, 1].plot(t_res, sol_res[:, 0]*1000, 'b-', linewidth=1)301axes[1, 1].set_xlabel('Time (s)')302axes[1, 1].set_ylabel('Displacement (mm)')303axes[1, 1].set_title(f'Response at Resonance ($\\omega = \\omega_n$)')304axes[1, 1].grid(True, alpha=0.3)305306plt.tight_layout()307save_fig('resonance.pdf')308309# Peak amplitude at resonance310X_resonance = F0/k / (2*zeta)311\end{pycode}312313\begin{figure}[H]314\centering315\includegraphics[width=\textwidth]{resonance.pdf}316\caption{Resonance characteristics: peak location, quality factor, bandwidth, and time response.}317\end{figure}318319\section{Transmissibility}320321Force transmitted to foundation:322\begin{equation}323TR = \frac{F_T}{F_0} = \sqrt{\frac{1 + (2\zeta r)^2}{(1-r^2)^2 + (2\zeta r)^2}}324\end{equation}325326\begin{pycode}327# Transmissibility328r = np.linspace(0.01, 4, 500)329zeta_values = [0.05, 0.1, 0.2, 0.5]330331fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))332333# Force transmissibility334for zeta_i in zeta_values:335TR = np.sqrt((1 + (2*zeta_i*r)**2) / ((1 - r**2)**2 + (2*zeta_i*r)**2))336ax1.plot(r, TR, linewidth=2, label=f'$\\zeta$ = {zeta_i}')337338ax1.axhline(1, color='k', linestyle='--', alpha=0.5)339ax1.axvline(np.sqrt(2), color='r', linestyle=':', alpha=0.5, label='$r = \\sqrt{2}$')340ax1.set_xlabel('Frequency Ratio $r$')341ax1.set_ylabel('Transmissibility $TR$')342ax1.set_title('Force Transmissibility')343ax1.legend()344ax1.grid(True, alpha=0.3)345ax1.set_ylim(0, 5)346347# Isolation efficiency348isolation = (1 - 1/TR) * 100 # When TR < 1 (r > sqrt(2))349for zeta_i in [0.1, 0.2]:350TR_i = np.sqrt((1 + (2*zeta_i*r)**2) / ((1 - r**2)**2 + (2*zeta_i*r)**2))351isolation_i = np.maximum(0, (1 - TR_i) * 100)352ax2.plot(r, isolation_i, linewidth=2, label=f'$\\zeta$ = {zeta_i}')353354ax2.axvline(np.sqrt(2), color='r', linestyle=':', alpha=0.5)355ax2.set_xlabel('Frequency Ratio $r$')356ax2.set_ylabel('Isolation Efficiency (\\%)')357ax2.set_title('Vibration Isolation')358ax2.legend()359ax2.grid(True, alpha=0.3)360361plt.tight_layout()362save_fig('transmissibility.pdf')363\end{pycode}364365\begin{figure}[H]366\centering367\includegraphics[width=\textwidth]{transmissibility.pdf}368\caption{Force transmissibility and vibration isolation efficiency.}369\end{figure}370371\section{Two-DOF System (Modal Analysis)}372373\begin{pycode}374# Two-DOF system375m1 = m2 = 1.0 # kg376k1 = k2 = k3 = 100 # N/m377378# Mass and stiffness matrices379M = np.array([[m1, 0], [0, m2]])380K = np.array([[k1+k2, -k2], [-k2, k2+k3]])381382# Eigenvalue problem383eigenvalues, eigenvectors = np.linalg.eig(np.linalg.inv(M) @ K)384omega_natural = np.sqrt(eigenvalues)385omega_sorted = np.sort(omega_natural)386387# Mode shapes388idx = np.argsort(eigenvalues)389modes = eigenvectors[:, idx]390modes = modes / modes[0, :] # Normalize to first component391392fig, axes = plt.subplots(2, 2, figsize=(12, 10))393394# Mode shape visualization395x = [0, 1, 2] # Node positions396mode1 = [0, modes[0, 0], modes[1, 0]]397mode2 = [0, modes[0, 1], modes[1, 1]]398399axes[0, 0].plot(x, mode1, 'bo-', linewidth=2, markersize=10, label=f'Mode 1: $\\omega$ = {omega_sorted[0]:.2f} rad/s')400axes[0, 0].axhline(0, color='k', linestyle='-', linewidth=0.5)401axes[0, 0].set_xlabel('DOF')402axes[0, 0].set_ylabel('Mode Shape Amplitude')403axes[0, 0].set_title('First Mode Shape')404axes[0, 0].legend()405axes[0, 0].grid(True, alpha=0.3)406407axes[0, 1].plot(x, mode2, 'ro-', linewidth=2, markersize=10, label=f'Mode 2: $\\omega$ = {omega_sorted[1]:.2f} rad/s')408axes[0, 1].axhline(0, color='k', linestyle='-', linewidth=0.5)409axes[0, 1].set_xlabel('DOF')410axes[0, 1].set_ylabel('Mode Shape Amplitude')411axes[0, 1].set_title('Second Mode Shape')412axes[0, 1].legend()413axes[0, 1].grid(True, alpha=0.3)414415# Free response of 2-DOF system416def two_dof_system(y, t, M, K, C):417x = y[:2]418v = y[2:]419a = np.linalg.inv(M) @ (-C @ v - K @ x)420return list(v) + list(a)421422C = 0.1 * K # Proportional damping423y0_2dof = [0.1, 0, 0, 0] # Initial conditions424t_2dof = np.linspace(0, 5, 1000)425sol_2dof = odeint(two_dof_system, y0_2dof, t_2dof, args=(M, K, C))426427axes[1, 0].plot(t_2dof, sol_2dof[:, 0]*1000, 'b-', linewidth=1.5, label='Mass 1')428axes[1, 0].plot(t_2dof, sol_2dof[:, 1]*1000, 'r-', linewidth=1.5, label='Mass 2')429axes[1, 0].set_xlabel('Time (s)')430axes[1, 0].set_ylabel('Displacement (mm)')431axes[1, 0].set_title('2-DOF Free Response')432axes[1, 0].legend()433axes[1, 0].grid(True, alpha=0.3)434435# FFT to identify natural frequencies436from scipy.fft import fft, fftfreq437N = len(t_2dof)438dt = t_2dof[1] - t_2dof[0]439yf = fft(sol_2dof[:, 0])440xf = fftfreq(N, dt)441442axes[1, 1].plot(xf[:N//2], 2/N * np.abs(yf[:N//2]), 'b-', linewidth=1.5)443axes[1, 1].axvline(omega_sorted[0]/(2*np.pi), color='r', linestyle='--', alpha=0.5)444axes[1, 1].axvline(omega_sorted[1]/(2*np.pi), color='r', linestyle='--', alpha=0.5)445axes[1, 1].set_xlabel('Frequency (Hz)')446axes[1, 1].set_ylabel('Amplitude')447axes[1, 1].set_title('Frequency Content (FFT)')448axes[1, 1].set_xlim(0, 5)449axes[1, 1].grid(True, alpha=0.3)450451plt.tight_layout()452save_fig('modal_analysis.pdf')453\end{pycode}454455\begin{figure}[H]456\centering457\includegraphics[width=\textwidth]{modal_analysis.pdf}458\caption{Modal analysis of 2-DOF system: mode shapes, time response, and FFT.}459\end{figure}460461Natural frequencies: $\omega_1 = \py{f"{omega_sorted[0]:.2f}"}$ rad/s, $\omega_2 = \py{f"{omega_sorted[1]:.2f}"}$ rad/s462463\section{Conclusions}464465This analysis demonstrates key aspects of vibration analysis:466\begin{enumerate}467\item SDOF systems are characterized by natural frequency and damping ratio468\item Logarithmic decrement provides experimental damping measurement469\item Resonance occurs near natural frequency with phase shift of 90 degrees470\item Vibration isolation requires $r > \sqrt{2}$471\item MDOF systems have multiple natural frequencies and mode shapes472\item FFT analysis identifies frequency content from time domain data473\end{enumerate}474475\end{document}476477478