Path: blob/main/latex-templates/templates/fluid-dynamics/navier_stokes.tex
51 views
unlisted
\documentclass[a4paper, 11pt]{article}1\usepackage[utf8]{inputenc}2\usepackage[T1]{fontenc}3\usepackage{amsmath, amssymb, amsthm}4\usepackage{graphicx}5\usepackage{siunitx}6\usepackage{booktabs}7\usepackage{float}8\usepackage{geometry}9\geometry{margin=1in}10\usepackage[makestderr]{pythontex}1112\newtheorem{theorem}{Theorem}[section]13\newtheorem{definition}[theorem]{Definition}1415\title{Navier-Stokes Equations: Viscous Flow Analysis\\and Boundary Layer Theory}16\author{Fluid Mechanics Research Laboratory}17\date{\today}1819\begin{document}20\maketitle2122\begin{abstract}23This technical report presents analytical and computational solutions to the Navier-Stokes equations for canonical viscous flow problems. We analyze Couette flow, Poiseuille flow, and boundary layer development using Python-based numerical methods. Results include velocity profiles, shear stress distributions, and Reynolds number effects on flow characteristics.24\end{abstract}2526\section{Introduction}2728The Navier-Stokes equations govern the motion of viscous fluids and form the foundation of fluid mechanics:29\begin{equation}30\rho\left(\frac{\partial \mathbf{u}}{\partial t} + \mathbf{u} \cdot \nabla \mathbf{u}\right) = -\nabla p + \mu \nabla^2 \mathbf{u} + \rho \mathbf{g}31\end{equation}3233\begin{definition}[Reynolds Number]34The Reynolds number characterizes the ratio of inertial to viscous forces:35\begin{equation}36Re = \frac{\rho U L}{\mu} = \frac{U L}{\nu}37\end{equation}38\end{definition}3940\section{Computational Setup}4142\begin{pycode}43import numpy as np44import matplotlib.pyplot as plt45from scipy.integrate import odeint, solve_bvp46from scipy.special import erfc4748plt.rc('text', usetex=True)49plt.rc('font', family='serif', size=9)50np.random.seed(42)5152# Fluid properties (water at 20C)53rho = 998.0 # kg/m^354mu = 1.002e-3 # Pa.s55nu = mu / rho # m^2/s5657# Geometric parameters58H = 0.01 # Channel height (m)59L = 0.1 # Channel length (m)60\end{pycode}6162\noindent\textbf{Fluid Properties (Water at 20$^\circ$C):}63\begin{itemize}64\item Density: $\rho = \py{rho}$ kg/m$^3$65\item Dynamic Viscosity: $\mu = \py{f"{mu*1000:.3f}"}$ mPa$\cdot$s66\item Kinematic Viscosity: $\nu = \py{f"{nu*1e6:.3f}"}$ mm$^2$/s67\end{itemize}6869\section{Couette Flow Analysis}7071Couette flow occurs between two parallel plates where one plate moves relative to the other.7273\begin{pycode}74# Couette flow: upper plate moving at U_wall75U_wall = 0.1 # m/s76y = np.linspace(0, H, 100)7778# Velocity profile (linear)79u_couette = U_wall * y / H8081# With pressure gradient (generalized Couette)82dpdx_values = [-1000, 0, 1000] # Pa/m83fig, axes = plt.subplots(2, 2, figsize=(10, 8))8485for dpdx in dpdx_values:86u_gen = U_wall * y/H - (1/(2*mu)) * dpdx * y * (H - y)87label = f'dp/dx = {dpdx} Pa/m'88axes[0, 0].plot(u_gen*1000, y*1000, linewidth=1.5, label=label)8990axes[0, 0].set_xlabel('Velocity (mm/s)')91axes[0, 0].set_ylabel('y (mm)')92axes[0, 0].set_title('Generalized Couette Flow')93axes[0, 0].legend(loc='upper left', fontsize=8)94axes[0, 0].grid(True, alpha=0.3)9596# Shear stress distribution97tau_couette = mu * U_wall / H98y_stress = np.linspace(0, H, 100)99tau_wall = mu * U_wall / H * np.ones_like(y_stress)100101# With pressure gradient102for dpdx in dpdx_values:103du_dy = U_wall/H - (1/(2*mu)) * dpdx * (H - 2*y_stress)104tau = mu * du_dy105axes[0, 1].plot(tau, y_stress*1000, linewidth=1.5)106107axes[0, 1].set_xlabel('Shear Stress (Pa)')108axes[0, 1].set_ylabel('y (mm)')109axes[0, 1].set_title('Shear Stress Distribution')110axes[0, 1].grid(True, alpha=0.3)111112# Time-dependent startup (Stokes first problem)113t_values = [0.01, 0.05, 0.1, 0.5, 1.0]114y_stokes = np.linspace(0, 5*H, 200)115116for t in t_values:117eta = y_stokes / (2 * np.sqrt(nu * t))118u_stokes = U_wall * erfc(eta)119axes[1, 0].plot(u_stokes*1000, y_stokes*1000, linewidth=1.5,120label=f't = {t} s')121122axes[1, 0].set_xlabel('Velocity (mm/s)')123axes[1, 0].set_ylabel('y (mm)')124axes[1, 0].set_title("Stokes' First Problem (Impulsive Start)")125axes[1, 0].legend(loc='upper right', fontsize=8)126axes[1, 0].grid(True, alpha=0.3)127128# Boundary layer thickness vs time129t_range = np.linspace(0.001, 2, 100)130delta_99 = 3.6 * np.sqrt(nu * t_range)131132axes[1, 1].plot(t_range, delta_99*1000, 'b-', linewidth=1.5)133axes[1, 1].set_xlabel('Time (s)')134axes[1, 1].set_ylabel('$\\delta_{99}$ (mm)')135axes[1, 1].set_title('Boundary Layer Growth')136axes[1, 1].grid(True, alpha=0.3)137138plt.tight_layout()139plt.savefig('navier_stokes_plot1.pdf', bbox_inches='tight', dpi=150)140plt.close()141142# Calculate key parameters143Re_couette = rho * U_wall * H / mu144tau_wall_couette = mu * U_wall / H145\end{pycode}146147\begin{figure}[H]148\centering149\includegraphics[width=0.95\textwidth]{navier_stokes_plot1.pdf}150\caption{Couette flow analysis: velocity profiles, shear stress, and transient development.}151\end{figure}152153\begin{table}[H]154\centering155\caption{Couette Flow Parameters}156\begin{tabular}{lcc}157\toprule158\textbf{Parameter} & \textbf{Value} & \textbf{Unit} \\159\midrule160Wall Velocity & \py{f"{U_wall*1000:.1f}"} & mm/s \\161Channel Height & \py{f"{H*1000:.1f}"} & mm \\162Reynolds Number & \py{f"{Re_couette:.2f}"} & -- \\163Wall Shear Stress & \py{f"{tau_wall_couette:.4f}"} & Pa \\164\bottomrule165\end{tabular}166\end{table}167168\section{Poiseuille Flow (Pressure-Driven)}169170\begin{theorem}[Hagen-Poiseuille Equation]171For laminar flow in a circular pipe, the volumetric flow rate is:172\begin{equation}173Q = \frac{\pi R^4}{8\mu}\left(-\frac{dp}{dx}\right)174\end{equation}175\end{theorem}176177\begin{pycode}178# Channel Poiseuille flow179dpdx = -1000 # Pa/m (negative for flow in +x direction)180181# Velocity profile182u_max = -(dpdx * H**2) / (8 * mu)183u_poiseuille = -(1/(2*mu)) * dpdx * y * (H - y)184u_avg = (2/3) * u_max185186# Pipe flow187R_pipe = H/2188r = np.linspace(-R_pipe, R_pipe, 100)189u_pipe = -(1/(4*mu)) * dpdx * (R_pipe**2 - r**2)190u_max_pipe = -(dpdx * R_pipe**2) / (4 * mu)191192# Flow rate calculations193Q_channel = (H**3 * (-dpdx)) / (12 * mu) # per unit width194Q_pipe = (np.pi * R_pipe**4 * (-dpdx)) / (8 * mu)195196fig, axes = plt.subplots(2, 2, figsize=(10, 8))197198# Channel velocity profile199axes[0, 0].plot(u_poiseuille*1000, y*1000, 'b-', linewidth=1.5, label='Velocity')200axes[0, 0].axhline(y=H*1000/2, color='r', linestyle='--', alpha=0.7)201axes[0, 0].axvline(x=u_max*1000, color='g', linestyle=':', alpha=0.7, label='$u_{max}$')202axes[0, 0].set_xlabel('Velocity (mm/s)')203axes[0, 0].set_ylabel('y (mm)')204axes[0, 0].set_title('Channel Poiseuille Flow')205axes[0, 0].legend(loc='upper right', fontsize=8)206axes[0, 0].grid(True, alpha=0.3)207208# Pipe velocity profile209axes[0, 1].plot(u_pipe*1000, r*1000, 'b-', linewidth=1.5)210axes[0, 1].axhline(y=0, color='r', linestyle='--', alpha=0.7)211axes[0, 1].set_xlabel('Velocity (mm/s)')212axes[0, 1].set_ylabel('r (mm)')213axes[0, 1].set_title('Pipe Poiseuille Flow')214axes[0, 1].grid(True, alpha=0.3)215216# Entrance length development217Re_pipe = rho * (u_avg * 2) * (2*R_pipe) / mu218Le_laminar = 0.06 * Re_pipe * (2*R_pipe)219220x_entrance = np.linspace(0, Le_laminar*1.5, 100)221# Developing velocity profiles at different x locations222x_positions = [0.1*Le_laminar, 0.3*Le_laminar, 0.6*Le_laminar, Le_laminar]223r_dev = np.linspace(0, R_pipe, 50)224225for i, x_pos in enumerate(x_positions):226# Approximate developing profile227alpha = min(1, x_pos/Le_laminar)228u_dev = u_avg * (1 + alpha * (2*(1-(r_dev/R_pipe)**2) - 1))229axes[1, 0].plot(u_dev*1000, r_dev*1000, linewidth=1.5,230label=f'x/Le = {x_pos/Le_laminar:.1f}')231232axes[1, 0].set_xlabel('Velocity (mm/s)')233axes[1, 0].set_ylabel('r (mm)')234axes[1, 0].set_title('Developing Flow in Entrance Region')235axes[1, 0].legend(loc='upper right', fontsize=8)236axes[1, 0].grid(True, alpha=0.3)237238# Reynolds number effect on velocity profile shape239Re_values = [100, 500, 1000, 2000]240for Re in Re_values:241U_Re = Re * nu / (2*R_pipe)242dpdx_Re = -8 * mu * U_Re / R_pipe**2243u_Re = -(1/(4*mu)) * dpdx_Re * (R_pipe**2 - r**2)244axes[1, 1].plot(u_Re/U_Re, r/R_pipe, linewidth=1.5, label=f'Re = {Re}')245246axes[1, 1].set_xlabel('$u/U_{avg}$')247axes[1, 1].set_ylabel('$r/R$')248axes[1, 1].set_title('Normalized Velocity Profiles')249axes[1, 1].legend(loc='upper right', fontsize=8)250axes[1, 1].grid(True, alpha=0.3)251252plt.tight_layout()253plt.savefig('navier_stokes_plot2.pdf', bbox_inches='tight', dpi=150)254plt.close()255\end{pycode}256257\begin{figure}[H]258\centering259\includegraphics[width=0.95\textwidth]{navier_stokes_plot2.pdf}260\caption{Poiseuille flow analysis: velocity profiles and entrance region development.}261\end{figure}262263\begin{table}[H]264\centering265\caption{Poiseuille Flow Results}266\begin{tabular}{lcc}267\toprule268\textbf{Parameter} & \textbf{Value} & \textbf{Unit} \\269\midrule270Maximum Velocity & \py{f"{u_max*1000:.2f}"} & mm/s \\271Average Velocity & \py{f"{u_avg*1000:.2f}"} & mm/s \\272Flow Rate (channel) & \py{f"{Q_channel*1e6:.3f}"} & mm$^2$/s \\273Reynolds Number & \py{f"{Re_pipe:.1f}"} & -- \\274Entrance Length & \py{f"{Le_laminar*1000:.1f}"} & mm \\275\bottomrule276\end{tabular}277\end{table}278279\section{Boundary Layer Analysis}280281\begin{pycode}282# Blasius boundary layer solution283# f''' + 0.5*f*f'' = 0 with f(0)=f'(0)=0, f'(inf)=1284285def blasius_ode(eta, f):286return [f[1], f[2], -0.5*f[0]*f[2]]287288# Shooting method to find correct f''(0)289from scipy.optimize import brentq290291def shoot_blasius(f2_0):292eta_span = [0, 10]293eta_eval = np.linspace(0, 10, 500)294f0 = [0, 0, f2_0]295sol = odeint(blasius_ode, f0, eta_eval)296return sol[-1, 1] - 1 # f'(inf) should be 1297298# Use bisection to find correct f''(0)299f2_0_correct = brentq(shoot_blasius, 0.1, 0.5)300301# Solve with correct initial condition302eta = np.linspace(0, 8, 500)303f0 = [0, 0, f2_0_correct]304sol = odeint(blasius_ode, f0, eta)305306f = sol[:, 0]307f_prime = sol[:, 1] # u/U_inf308f_double_prime = sol[:, 2]309310# Boundary layer parameters311U_inf = 1.0 # Free stream velocity (m/s)312x_values = np.array([0.01, 0.05, 0.1, 0.2, 0.5])313314fig, axes = plt.subplots(2, 2, figsize=(10, 8))315316# Blasius velocity profile317axes[0, 0].plot(f_prime, eta, 'b-', linewidth=1.5)318axes[0, 0].axhline(y=5.0, color='r', linestyle='--', alpha=0.7, label='$\\eta = 5$')319axes[0, 0].axvline(x=0.99, color='g', linestyle=':', alpha=0.7, label='$u/U_\\infty = 0.99$')320axes[0, 0].set_xlabel('$u/U_\\infty$')321axes[0, 0].set_ylabel('$\\eta = y\\sqrt{U_\\infty/\\nu x}$')322axes[0, 0].set_title('Blasius Velocity Profile')323axes[0, 0].legend(loc='lower right', fontsize=8)324axes[0, 0].grid(True, alpha=0.3)325326# Boundary layer thickness along plate327Re_x = U_inf * x_values / nu328delta = 5.0 * x_values / np.sqrt(Re_x)329delta_star = 1.72 * x_values / np.sqrt(Re_x)330theta = 0.664 * x_values / np.sqrt(Re_x)331332axes[0, 1].plot(x_values*1000, delta*1000, 'b-', linewidth=1.5, label='$\\delta$')333axes[0, 1].plot(x_values*1000, delta_star*1000, 'r--', linewidth=1.5, label='$\\delta^*$')334axes[0, 1].plot(x_values*1000, theta*1000, 'g:', linewidth=1.5, label='$\\theta$')335axes[0, 1].set_xlabel('x (mm)')336axes[0, 1].set_ylabel('Thickness (mm)')337axes[0, 1].set_title('Boundary Layer Thickness Growth')338axes[0, 1].legend(loc='upper left', fontsize=8)339axes[0, 1].grid(True, alpha=0.3)340341# Skin friction coefficient342Cf = 0.664 / np.sqrt(Re_x)343axes[1, 0].loglog(Re_x, Cf, 'b-', linewidth=1.5, label='Laminar (Blasius)')344# Turbulent comparison345Re_x_turb = np.logspace(5, 7, 100)346Cf_turb = 0.027 / Re_x_turb**(1/7)347axes[1, 0].loglog(Re_x_turb, Cf_turb, 'r--', linewidth=1.5, label='Turbulent')348axes[1, 0].set_xlabel('$Re_x$')349axes[1, 0].set_ylabel('$C_f$')350axes[1, 0].set_title('Skin Friction Coefficient')351axes[1, 0].legend(loc='upper right', fontsize=8)352axes[1, 0].grid(True, which='both', alpha=0.3)353354# Wall shear stress355tau_w = 0.332 * rho * U_inf**2 / np.sqrt(Re_x)356axes[1, 1].plot(x_values*1000, tau_w, 'b-', linewidth=1.5, marker='o')357axes[1, 1].set_xlabel('x (mm)')358axes[1, 1].set_ylabel('$\\tau_w$ (Pa)')359axes[1, 1].set_title('Wall Shear Stress Distribution')360axes[1, 1].grid(True, alpha=0.3)361362plt.tight_layout()363plt.savefig('navier_stokes_plot3.pdf', bbox_inches='tight', dpi=150)364plt.close()365366# Calculate shape factor367H_factor = delta_star / theta368\end{pycode}369370\begin{figure}[H]371\centering372\includegraphics[width=0.95\textwidth]{navier_stokes_plot3.pdf}373\caption{Blasius boundary layer solution: velocity profile, thickness growth, and skin friction.}374\end{figure}375376\section{Reynolds Number Effects}377378\begin{pycode}379# Reynolds number effects on flow characteristics380Re_range = np.logspace(0, 4, 100)381382# Critical Reynolds numbers383Re_crit_pipe = 2300384Re_crit_plate = 5e5385386# Friction factor for pipe flow387def friction_factor(Re):388if Re < 2300:389return 64 / Re390else:391return 0.316 / Re**0.25392393f_factor = np.array([friction_factor(Re) for Re in Re_range])394395fig, axes = plt.subplots(2, 2, figsize=(10, 8))396397# Friction factor vs Re398axes[0, 0].loglog(Re_range, f_factor, 'b-', linewidth=1.5)399axes[0, 0].axvline(x=Re_crit_pipe, color='r', linestyle='--', alpha=0.7, label='Transition')400axes[0, 0].set_xlabel('Re')401axes[0, 0].set_ylabel('Friction Factor $f$')402axes[0, 0].set_title('Moody Diagram (Smooth Pipe)')403axes[0, 0].legend(loc='upper right', fontsize=8)404axes[0, 0].grid(True, which='both', alpha=0.3)405406# Velocity profiles at different Re407y_norm = np.linspace(0, 1, 100)408for Re in [100, 1000, 5000]:409if Re < 2300:410u_norm = 1.5 * (1 - (2*y_norm - 1)**2)411else:412n = 7413u_norm = (y_norm)**(1/n)414axes[0, 1].plot(u_norm, y_norm, linewidth=1.5, label=f'Re = {Re}')415416axes[0, 1].set_xlabel('$u/u_{max}$')417axes[0, 1].set_ylabel('$y/H$')418axes[0, 1].set_title('Velocity Profile Shape vs Re')419axes[0, 1].legend(loc='lower right', fontsize=8)420axes[0, 1].grid(True, alpha=0.3)421422# Pressure drop vs flow rate423Q_range = np.linspace(1e-6, 1e-4, 100)424D_pipe = 0.01425L_pipe = 1.0426427def pressure_drop(Q, D, L_p):428A = np.pi * D**2 / 4429V = Q / A430Re = rho * V * D / mu431f = friction_factor(Re)432return f * (L_p/D) * (rho * V**2 / 2)433434dp_range = np.array([pressure_drop(Q, D_pipe, L_pipe) for Q in Q_range])435436axes[1, 0].plot(Q_range*1e6, dp_range/1000, 'b-', linewidth=1.5)437axes[1, 0].set_xlabel('Flow Rate (mL/s)')438axes[1, 0].set_ylabel('Pressure Drop (kPa)')439axes[1, 0].set_title('Pressure Drop vs Flow Rate')440axes[1, 0].grid(True, alpha=0.3)441442# Entrance length443Re_entrance = np.logspace(1, 4, 100)444Le_lam = 0.06 * Re_entrance * D_pipe445Le_turb = 4.4 * Re_entrance**(1/6) * D_pipe446447axes[1, 1].loglog(Re_entrance, Le_lam*1000, 'b-', linewidth=1.5, label='Laminar')448axes[1, 1].loglog(Re_entrance[Re_entrance>2300], Le_turb[Re_entrance>2300]*1000,449'r--', linewidth=1.5, label='Turbulent')450axes[1, 1].axvline(x=2300, color='g', linestyle=':', alpha=0.7)451axes[1, 1].set_xlabel('Re')452axes[1, 1].set_ylabel('Entrance Length (mm)')453axes[1, 1].set_title('Entrance Length vs Reynolds Number')454axes[1, 1].legend(loc='upper left', fontsize=8)455axes[1, 1].grid(True, which='both', alpha=0.3)456457plt.tight_layout()458plt.savefig('navier_stokes_plot4.pdf', bbox_inches='tight', dpi=150)459plt.close()460\end{pycode}461462\begin{figure}[H]463\centering464\includegraphics[width=0.95\textwidth]{navier_stokes_plot4.pdf}465\caption{Reynolds number effects on flow characteristics.}466\end{figure}467468\section{Vorticity and Stream Function}469470\begin{pycode}471# 2D flow visualization using stream function472N = 50473x_grid = np.linspace(0, L, N)474y_grid = np.linspace(0, H, N)475X, Y = np.meshgrid(x_grid, y_grid)476477# Analytical solution for Stokes flow in cavity (first mode)478psi = np.sin(np.pi * X / L) * np.sinh(np.pi * Y / L)479480# Velocity components481u_field = np.pi/L * np.sin(np.pi * X / L) * np.cosh(np.pi * Y / L)482v_field = -np.pi/L * np.cos(np.pi * X / L) * np.sinh(np.pi * Y / L)483484# Vorticity485omega_field = np.gradient(v_field, x_grid, axis=1) - np.gradient(u_field, y_grid, axis=0)486487fig, axes = plt.subplots(2, 2, figsize=(10, 8))488489# Stream function contours490cs1 = axes[0, 0].contour(X*1000, Y*1000, psi, levels=20, cmap='coolwarm')491axes[0, 0].set_xlabel('x (mm)')492axes[0, 0].set_ylabel('y (mm)')493axes[0, 0].set_title('Stream Function $\\psi$')494axes[0, 0].set_aspect('equal')495plt.colorbar(cs1, ax=axes[0, 0])496497# Velocity magnitude498vel_mag = np.sqrt(u_field**2 + v_field**2)499cs2 = axes[0, 1].contourf(X*1000, Y*1000, vel_mag, levels=20, cmap='viridis')500axes[0, 1].set_xlabel('x (mm)')501axes[0, 1].set_ylabel('y (mm)')502axes[0, 1].set_title('Velocity Magnitude')503axes[0, 1].set_aspect('equal')504plt.colorbar(cs2, ax=axes[0, 1])505506# Vorticity field507cs3 = axes[1, 0].contourf(X*1000, Y*1000, omega_field, levels=20, cmap='RdBu_r')508axes[1, 0].set_xlabel('x (mm)')509axes[1, 0].set_ylabel('y (mm)')510axes[1, 0].set_title('Vorticity $\\omega$')511axes[1, 0].set_aspect('equal')512plt.colorbar(cs3, ax=axes[1, 0])513514# Velocity vectors515skip = 3516axes[1, 1].quiver(X[::skip, ::skip]*1000, Y[::skip, ::skip]*1000,517u_field[::skip, ::skip], v_field[::skip, ::skip],518scale=50, alpha=0.7)519axes[1, 1].set_xlabel('x (mm)')520axes[1, 1].set_ylabel('y (mm)')521axes[1, 1].set_title('Velocity Vectors')522axes[1, 1].set_aspect('equal')523524plt.tight_layout()525plt.savefig('navier_stokes_plot5.pdf', bbox_inches='tight', dpi=150)526plt.close()527\end{pycode}528529\begin{figure}[H]530\centering531\includegraphics[width=0.95\textwidth]{navier_stokes_plot5.pdf}532\caption{Flow field visualization: stream function, velocity magnitude, vorticity, and vectors.}533\end{figure}534535\section{Oscillatory Flow (Stokes' Second Problem)}536537\begin{pycode}538# Oscillating plate problem539omega_osc = 2 * np.pi540delta_stokes = np.sqrt(2 * nu / omega_osc)541542y_osc = np.linspace(0, 10*delta_stokes, 200)543t_osc_values = np.linspace(0, 2*np.pi/omega_osc, 8)544545fig, axes = plt.subplots(2, 2, figsize=(10, 8))546547# Velocity profiles at different phases548for i, t in enumerate(t_osc_values[:-1]):549phase = omega_osc * t550u_osc = U_wall * np.exp(-y_osc/delta_stokes) * np.cos(phase - y_osc/delta_stokes)551axes[0, 0].plot(u_osc*1000, y_osc/delta_stokes, linewidth=1,552label=f'$\\omega t$ = {np.rad2deg(phase):.0f}')553554axes[0, 0].axvline(x=0, color='gray', linestyle='-', alpha=0.3)555axes[0, 0].set_xlabel('Velocity (mm/s)')556axes[0, 0].set_ylabel('$y/\\delta_s$')557axes[0, 0].set_title("Stokes' Second Problem")558axes[0, 0].legend(loc='upper right', fontsize=7)559axes[0, 0].grid(True, alpha=0.3)560561# Amplitude decay562amplitude = U_wall * np.exp(-y_osc/delta_stokes)563axes[0, 1].plot(amplitude*1000, y_osc/delta_stokes, 'b-', linewidth=1.5)564axes[0, 1].axhline(y=1, color='r', linestyle='--', alpha=0.7, label='$\\delta_s$')565axes[0, 1].set_xlabel('Amplitude (mm/s)')566axes[0, 1].set_ylabel('$y/\\delta_s$')567axes[0, 1].set_title('Velocity Amplitude Decay')568axes[0, 1].legend(loc='upper right', fontsize=8)569axes[0, 1].grid(True, alpha=0.3)570571# Phase lag572phase_lag = y_osc / delta_stokes573axes[1, 0].plot(np.rad2deg(phase_lag), y_osc/delta_stokes, 'b-', linewidth=1.5)574axes[1, 0].set_xlabel('Phase Lag (degrees)')575axes[1, 0].set_ylabel('$y/\\delta_s$')576axes[1, 0].set_title('Phase Lag with Distance')577axes[1, 0].grid(True, alpha=0.3)578579# Stokes layer thickness vs frequency580freq_range = np.logspace(-1, 2, 100)581omega_range = 2 * np.pi * freq_range582delta_range = np.sqrt(2 * nu / omega_range)583584axes[1, 1].loglog(freq_range, delta_range*1000, 'b-', linewidth=1.5)585axes[1, 1].set_xlabel('Frequency (Hz)')586axes[1, 1].set_ylabel('$\\delta_s$ (mm)')587axes[1, 1].set_title('Stokes Layer Thickness vs Frequency')588axes[1, 1].grid(True, which='both', alpha=0.3)589590plt.tight_layout()591plt.savefig('navier_stokes_plot6.pdf', bbox_inches='tight', dpi=150)592plt.close()593\end{pycode}594595\begin{figure}[H]596\centering597\includegraphics[width=0.95\textwidth]{navier_stokes_plot6.pdf}598\caption{Oscillatory flow: Stokes' second problem and Stokes layer characteristics.}599\end{figure}600601\begin{table}[H]602\centering603\caption{Oscillatory Flow Parameters}604\begin{tabular}{lcc}605\toprule606\textbf{Parameter} & \textbf{Value} & \textbf{Unit} \\607\midrule608Oscillation Frequency & \py{f"{omega_osc/(2*np.pi):.2f}"} & Hz \\609Stokes Layer Thickness & \py{f"{delta_stokes*1000:.3f}"} & mm \\610Penetration Depth ($3\delta_s$) & \py{f"{3*delta_stokes*1000:.3f}"} & mm \\611\bottomrule612\end{tabular}613\end{table}614615\section{Conclusions}616617This analysis of the Navier-Stokes equations demonstrated:618619\begin{enumerate}620\item \textbf{Couette Flow}: Linear velocity profile with wall shear stress $\tau_w = \py{f"{tau_wall_couette:.4f}"}$ Pa. Generalized solutions with pressure gradients show parabolic modifications.621622\item \textbf{Poiseuille Flow}: Parabolic velocity profile with maximum velocity $u_{max} = \py{f"{u_max*1000:.2f}"}$ mm/s. The entrance length scales linearly with Reynolds number for laminar flow.623624\item \textbf{Boundary Layers}: Blasius solution gives $f''(0) = \py{f"{f2_0_correct:.4f}"}$, with boundary layer thickness $\delta \propto x^{1/2}$.625626\item \textbf{Reynolds Number Effects}: Critical $Re = 2300$ for pipe flow transition, with friction factor following the Blasius correlation in turbulent regime.627628\item \textbf{Oscillatory Flows}: Stokes layer thickness $\delta_s = \py{f"{delta_stokes*1000:.3f}"}$ mm determines penetration depth of oscillations.629\end{enumerate}630631\end{document}632633634