Path: blob/main/latex-templates/templates/mechanical-engineering/fluid_flow.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{Pipe Flow Analysis: Darcy-Weisbach and Friction Factors}18\author{Mechanical Engineering Laboratory}19\date{\today}2021\begin{document}22\maketitle2324\begin{abstract}25This report presents computational analysis of pipe flow using the Darcy-Weisbach equation. We examine Reynolds number regimes, friction factor correlations including the Colebrook-White equation, the Moody diagram, minor losses, and pipe network analysis. Python-based computations provide quantitative analysis with dynamic visualization.26\end{abstract}2728\tableofcontents29\newpage3031\section{Introduction to Pipe Flow}3233Internal flow through pipes is fundamental to hydraulic system design. Key applications include:34\begin{itemize}35\item Water distribution networks36\item Oil and gas pipelines37\item HVAC systems38\item Process piping in chemical plants39\end{itemize}4041% Initialize Python environment42\begin{pycode}43import numpy as np44import matplotlib.pyplot as plt45from scipy.optimize import fsolve4647plt.rcParams['figure.figsize'] = (8, 5)48plt.rcParams['font.size'] = 1049plt.rcParams['text.usetex'] = True5051def save_fig(filename):52plt.savefig(filename, dpi=150, bbox_inches='tight')53plt.close()54\end{pycode}5556\section{Fundamental Equations}5758\subsection{Reynolds Number}5960The Reynolds number characterizes flow regime:61\begin{equation}62Re = \frac{\rho V D}{\mu} = \frac{V D}{\nu}63\end{equation}64where $\rho$ is density, $V$ is velocity, $D$ is diameter, and $\mu$ is dynamic viscosity.6566\begin{pycode}67# Flow regime visualization68Re_range = np.logspace(2, 6, 500)6970fig, ax = plt.subplots(figsize=(10, 5))7172# Laminar regime73ax.axvspan(100, 2300, alpha=0.3, color='blue', label='Laminar')74# Transition regime75ax.axvspan(2300, 4000, alpha=0.3, color='yellow', label='Transition')76# Turbulent regime77ax.axvspan(4000, 1e6, alpha=0.3, color='red', label='Turbulent')7879ax.axvline(2300, color='black', linestyle='--', linewidth=2)80ax.axvline(4000, color='black', linestyle='--', linewidth=2)8182ax.set_xscale('log')83ax.set_xlabel('Reynolds Number')84ax.set_ylabel('Flow Characteristic')85ax.set_title('Flow Regime Classification')86ax.legend(loc='upper left')87ax.set_xlim(100, 1e6)88ax.set_yticks([])8990# Add annotations91ax.text(500, 0.5, 'Laminar\\n$Re < 2300$', ha='center', fontsize=12, transform=ax.get_xaxis_transform())92ax.text(3100, 0.5, 'Trans.', ha='center', fontsize=10, transform=ax.get_xaxis_transform())93ax.text(50000, 0.5, 'Turbulent\\n$Re > 4000$', ha='center', fontsize=12, transform=ax.get_xaxis_transform())9495save_fig('flow_regimes.pdf')96\end{pycode}9798\begin{figure}[H]99\centering100\includegraphics[width=\textwidth]{flow_regimes.pdf}101\caption{Flow regime classification based on Reynolds number.}102\end{figure}103104\subsection{Darcy-Weisbach Equation}105106Head loss in pipe flow:107\begin{equation}108h_f = f \frac{L}{D} \frac{V^2}{2g}109\end{equation}110or in terms of pressure drop:111\begin{equation}112\Delta P = f \frac{L}{D} \frac{\rho V^2}{2}113\end{equation}114115\section{Friction Factor Correlations}116117\subsection{Laminar Flow}118119For laminar flow ($Re < 2300$):120\begin{equation}121f = \frac{64}{Re}122\end{equation}123124\subsection{Turbulent Flow - Colebrook-White Equation}125126For turbulent flow:127\begin{equation}128\frac{1}{\sqrt{f}} = -2\log_{10}\left(\frac{\epsilon/D}{3.7} + \frac{2.51}{Re\sqrt{f}}\right)129\end{equation}130131\begin{pycode}132# Friction factor calculation functions133def f_laminar(Re):134return 64 / Re135136def f_turbulent(Re, eps_D):137"""Solve Colebrook-White equation iteratively"""138if Re < 2300:139return 64 / Re140141# Swamee-Jain initial guess142f0 = 0.25 / (np.log10(eps_D/3.7 + 5.74/Re**0.9))**2143144# Newton-Raphson iteration145for _ in range(50):146sqrt_f = np.sqrt(f0)147LHS = 1/sqrt_f148RHS = -2 * np.log10(eps_D/3.7 + 2.51/(Re*sqrt_f))149f_new = 1/(RHS)**2150if abs(f_new - f0) < 1e-10:151break152f0 = f_new153154return f0155156# Calculate friction factors for various Reynolds numbers and roughness157Re_range = np.logspace(3, 8, 200)158eps_D_values = [0, 1e-6, 1e-5, 1e-4, 1e-3, 0.01, 0.05]159160fig, ax = plt.subplots(figsize=(12, 8))161162# Laminar line163Re_lam = np.linspace(600, 2300, 100)164f_lam = [f_laminar(Re) for Re in Re_lam]165ax.loglog(Re_lam, f_lam, 'b-', linewidth=2, label='Laminar')166167# Turbulent lines168colors = plt.cm.viridis(np.linspace(0, 1, len(eps_D_values)))169for eps_D, color in zip(eps_D_values, colors):170Re_turb = Re_range[Re_range > 2300]171f_turb = [f_turbulent(Re, eps_D) for Re in Re_turb]172if eps_D == 0:173label = 'Smooth'174else:175label = f'$\\epsilon/D$ = {eps_D}'176ax.loglog(Re_turb, f_turb, color=color, linewidth=1.5, label=label)177178ax.axvline(2300, color='gray', linestyle='--', alpha=0.5)179ax.set_xlabel('Reynolds Number, Re')180ax.set_ylabel('Friction Factor, f')181ax.set_title('Moody Diagram')182ax.legend(loc='upper right', fontsize=8)183ax.grid(True, which='both', alpha=0.3)184ax.set_xlim(600, 1e8)185ax.set_ylim(0.008, 0.1)186187save_fig('moody_diagram.pdf')188\end{pycode}189190\begin{figure}[H]191\centering192\includegraphics[width=\textwidth]{moody_diagram.pdf}193\caption{Moody diagram showing friction factor vs Reynolds number for various relative roughness values.}194\end{figure}195196\section{Pipe Flow Analysis}197198\begin{pycode}199# Design problem: water flow in commercial steel pipe200# Properties201rho = 998 # kg/m^3 (water)202mu = 0.001 # Pa*s203nu = mu / rho204205# Pipe parameters206D = 0.1 # m (100 mm diameter)207L = 100 # m208epsilon = 0.045e-3 # m (commercial steel)209eps_D = epsilon / D210211# Flow rates212Q_range = np.linspace(0.001, 0.05, 50) # m^3/s213V_range = Q_range / (np.pi * D**2 / 4)214Re_range = V_range * D / nu215216# Calculate friction factors and pressure drops217f_range = [f_turbulent(Re, eps_D) for Re in Re_range]218dP_range = np.array(f_range) * L/D * rho * V_range**2 / 2 # Pa219h_f_range = dP_range / (rho * 9.81) # m220221fig, axes = plt.subplots(2, 2, figsize=(12, 10))222223# Velocity vs flow rate224axes[0, 0].plot(Q_range*1000, V_range, 'b-', linewidth=2)225axes[0, 0].set_xlabel('Flow Rate (L/s)')226axes[0, 0].set_ylabel('Velocity (m/s)')227axes[0, 0].set_title('Flow Velocity')228axes[0, 0].grid(True, alpha=0.3)229230# Reynolds number231axes[0, 1].plot(Q_range*1000, Re_range/1000, 'r-', linewidth=2)232axes[0, 1].axhline(2.3, color='k', linestyle='--', alpha=0.5, label='Re = 2300')233axes[0, 1].set_xlabel('Flow Rate (L/s)')234axes[0, 1].set_ylabel('Reynolds Number ($\\times 10^3$)')235axes[0, 1].set_title('Reynolds Number')236axes[0, 1].legend()237axes[0, 1].grid(True, alpha=0.3)238239# Pressure drop240axes[1, 0].plot(Q_range*1000, dP_range/1000, 'g-', linewidth=2)241axes[1, 0].set_xlabel('Flow Rate (L/s)')242axes[1, 0].set_ylabel('Pressure Drop (kPa)')243axes[1, 0].set_title('Pressure Drop')244axes[1, 0].grid(True, alpha=0.3)245246# System curve (head loss vs flow rate)247axes[1, 1].plot(Q_range*1000, h_f_range, 'm-', linewidth=2, label='System curve')248axes[1, 1].set_xlabel('Flow Rate (L/s)')249axes[1, 1].set_ylabel('Head Loss (m)')250axes[1, 1].set_title('System Curve')251axes[1, 1].grid(True, alpha=0.3)252253plt.tight_layout()254save_fig('pipe_flow_analysis.pdf')255256# Design point calculations257Q_design = 0.02 # m^3/s (20 L/s)258V_design = Q_design / (np.pi * D**2 / 4)259Re_design = V_design * D / nu260f_design = f_turbulent(Re_design, eps_D)261dP_design = f_design * L/D * rho * V_design**2 / 2262h_f_design = dP_design / (rho * 9.81)263\end{pycode}264265\begin{figure}[H]266\centering267\includegraphics[width=\textwidth]{pipe_flow_analysis.pdf}268\caption{Pipe flow analysis showing velocity, Reynolds number, pressure drop, and system curve.}269\end{figure}270271\subsection{Design Point Results}272273For a design flow rate of $Q = 20$ L/s:274275\begin{table}[H]276\centering277\caption{Pipe Flow Design Calculations}278\begin{tabular}{lcc}279\toprule280Parameter & Value & Units \\281\midrule282Velocity & \py{f"{V_design:.2f}"} & m/s \\283Reynolds number & \py{f"{Re_design:.0f}"} & -- \\284Friction factor & \py{f"{f_design:.4f}"} & -- \\285Pressure drop & \py{f"{dP_design/1000:.2f}"} & kPa \\286Head loss & \py{f"{h_f_design:.2f}"} & m \\287\bottomrule288\end{tabular}289\end{table}290291\section{Minor Losses}292293Minor (local) losses from fittings and valves:294\begin{equation}295h_m = K \frac{V^2}{2g}296\end{equation}297298\begin{pycode}299# Minor loss coefficients300fittings = {301'90 elbow (regular)': 0.9,302'90 elbow (long radius)': 0.6,303'45 elbow': 0.4,304'Tee (branch)': 1.8,305'Gate valve (full open)': 0.2,306'Globe valve (full open)': 10.0,307'Check valve': 2.5,308'Entrance (sharp)': 0.5,309'Exit': 1.0310}311312fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))313314# Bar chart of K values315names = list(fittings.keys())316K_vals = list(fittings.values())317y_pos = np.arange(len(names))318319ax1.barh(y_pos, K_vals, color='steelblue', alpha=0.7)320ax1.set_yticks(y_pos)321ax1.set_yticklabels(names)322ax1.set_xlabel('Loss Coefficient K')323ax1.set_title('Minor Loss Coefficients')324ax1.grid(True, alpha=0.3, axis='x')325326# Total system losses with fittings327# Example system: entrance + 4 elbows + gate valve + exit328system_fittings = [329('Entrance', 0.5),330('4x 90 elbows', 4*0.9),331('Gate valve', 0.2),332('Exit', 1.0)333]334335V = V_design336g = 9.81337minor_losses = []338labels = []339for name, K in system_fittings:340h_m = K * V**2 / (2*g)341minor_losses.append(h_m)342labels.append(name)343344# Add major loss345major_loss = h_f_design346labels.append('Major loss')347minor_losses.append(major_loss)348349colors = ['lightblue']*4 + ['salmon']350ax2.bar(labels, minor_losses, color=colors, alpha=0.7)351ax2.set_ylabel('Head Loss (m)')352ax2.set_title('System Head Loss Breakdown')353ax2.grid(True, alpha=0.3, axis='y')354355total_loss = sum(minor_losses)356ax2.axhline(total_loss/len(minor_losses), color='red', linestyle='--',357label=f'Total = {total_loss:.2f} m')358ax2.legend()359360plt.tight_layout()361save_fig('minor_losses.pdf')362363K_total_minor = sum([k for _, k in system_fittings])364h_minor_total = K_total_minor * V_design**2 / (2*g)365\end{pycode}366367\begin{figure}[H]368\centering369\includegraphics[width=\textwidth]{minor_losses.pdf}370\caption{Minor loss coefficients and system head loss breakdown.}371\end{figure}372373Total minor losses: $h_m = \py{f"{h_minor_total:.2f}"}$ m374375\section{Pipe Diameter Effect}376377\begin{pycode}378# Effect of pipe diameter on pressure drop379diameters = np.linspace(0.05, 0.3, 100) # m380Q_fixed = 0.02 # m^3/s381382dP_diam = []383V_diam = []384385for D in diameters:386A = np.pi * D**2 / 4387V = Q_fixed / A388Re = V * D / nu389eps_D = epsilon / D390f = f_turbulent(Re, eps_D)391dP = f * L/D * rho * V**2 / 2392dP_diam.append(dP)393V_diam.append(V)394395fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))396397ax1.semilogy(diameters*1000, np.array(dP_diam)/1000, 'b-', linewidth=2)398ax1.axvline(100, color='r', linestyle='--', label='D = 100 mm')399ax1.set_xlabel('Pipe Diameter (mm)')400ax1.set_ylabel('Pressure Drop (kPa)')401ax1.set_title('Pressure Drop vs Diameter (Q = 20 L/s)')402ax1.legend()403ax1.grid(True, alpha=0.3)404405ax2.plot(diameters*1000, V_diam, 'g-', linewidth=2)406ax2.axhline(3, color='r', linestyle='--', alpha=0.5, label='Typical max V')407ax2.set_xlabel('Pipe Diameter (mm)')408ax2.set_ylabel('Flow Velocity (m/s)')409ax2.set_title('Velocity vs Diameter')410ax2.legend()411ax2.grid(True, alpha=0.3)412413plt.tight_layout()414save_fig('diameter_effect.pdf')415\end{pycode}416417\begin{figure}[H]418\centering419\includegraphics[width=\textwidth]{diameter_effect.pdf}420\caption{Effect of pipe diameter on pressure drop and velocity for constant flow rate.}421\end{figure}422423\section{Pipe Network Analysis}424425\subsection{Pipes in Series}426427For pipes in series, flow rate is constant and head losses add:428\begin{equation}429h_{f,total} = \sum_{i=1}^{n} h_{f,i}430\end{equation}431432\subsection{Pipes in Parallel}433434For pipes in parallel, head loss is equal and flow rates add:435\begin{equation}436Q_{total} = \sum_{i=1}^{n} Q_i \quad \text{with} \quad h_{f,1} = h_{f,2} = \cdots437\end{equation}438439\begin{pycode}440# Parallel pipe analysis441# Two pipes with different diameters442D1 = 0.1 # m443D2 = 0.08 # m444L_both = 100 # m445446# Find flow distribution for given total head loss447h_f_target = 5 # m target head loss448449def flow_rate_from_head(h_f, D, L, eps):450"""Calculate flow rate given head loss using iteration"""451eps_D = eps / D452A = np.pi * D**2 / 4453454# Initial guess using Hazen-Williams approximation455V = np.sqrt(2 * 9.81 * h_f * D / (0.02 * L))456457for _ in range(50):458Re = V * D / nu459f = f_turbulent(Re, eps_D)460V_new = np.sqrt(2 * 9.81 * h_f * D / (f * L))461if abs(V_new - V) < 1e-6:462break463V = V_new464465return V * A466467h_range = np.linspace(1, 10, 50)468Q1_range = [flow_rate_from_head(h, D1, L_both, epsilon) for h in h_range]469Q2_range = [flow_rate_from_head(h, D2, L_both, epsilon) for h in h_range]470Q_total = [q1 + q2 for q1, q2 in zip(Q1_range, Q2_range)]471472fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))473474ax1.plot(np.array(Q1_range)*1000, h_range, 'b-', linewidth=2, label=f'Pipe 1 (D={D1*1000:.0f}mm)')475ax1.plot(np.array(Q2_range)*1000, h_range, 'r-', linewidth=2, label=f'Pipe 2 (D={D2*1000:.0f}mm)')476ax1.plot(np.array(Q_total)*1000, h_range, 'k--', linewidth=2, label='Total')477ax1.set_xlabel('Flow Rate (L/s)')478ax1.set_ylabel('Head Loss (m)')479ax1.set_title('Parallel Pipe System Curves')480ax1.legend()481ax1.grid(True, alpha=0.3)482483# Flow distribution at target head loss484Q1_target = flow_rate_from_head(h_f_target, D1, L_both, epsilon)485Q2_target = flow_rate_from_head(h_f_target, D2, L_both, epsilon)486Q_total_target = Q1_target + Q2_target487488fractions = [Q1_target/Q_total_target * 100, Q2_target/Q_total_target * 100]489labels = [f'Pipe 1\\n{Q1_target*1000:.1f} L/s', f'Pipe 2\\n{Q2_target*1000:.1f} L/s']490ax2.pie(fractions, labels=labels, autopct='%1.1f%%', colors=['lightblue', 'salmon'])491ax2.set_title(f'Flow Distribution at $h_f$ = {h_f_target} m')492493plt.tight_layout()494save_fig('parallel_pipes.pdf')495\end{pycode}496497\begin{figure}[H]498\centering499\includegraphics[width=\textwidth]{parallel_pipes.pdf}500\caption{Parallel pipe analysis showing system curves and flow distribution.}501\end{figure}502503\section{Pump Selection}504505\begin{pycode}506# Pump operating point determination507# System curve: h_sys = h_static + K*Q^2508h_static = 10 # m (elevation difference)509K_sys = 50000 # system constant (s^2/m^5)510511Q_sys = np.linspace(0, 0.04, 100)512h_sys = h_static + K_sys * Q_sys**2513514# Pump curve (typical centrifugal)515h_shutoff = 25 # m516Q_max = 0.05 # m^3/s517h_pump = h_shutoff * (1 - (Q_sys/Q_max)**2)518519# Find operating point520idx_op = np.argmin(np.abs(h_pump - h_sys))521Q_op = Q_sys[idx_op]522h_op = h_pump[idx_op]523524# NPSH requirements525NPSH_r = 2 + 5 * (Q_sys/Q_max)**2 # typical requirement curve526527fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))528529ax1.plot(Q_sys*1000, h_sys, 'b-', linewidth=2, label='System curve')530ax1.plot(Q_sys*1000, h_pump, 'r-', linewidth=2, label='Pump curve')531ax1.plot(Q_op*1000, h_op, 'go', markersize=10, label=f'Operating point\\n({Q_op*1000:.1f} L/s, {h_op:.1f} m)')532ax1.set_xlabel('Flow Rate (L/s)')533ax1.set_ylabel('Head (m)')534ax1.set_title('Pump Operating Point')535ax1.legend()536ax1.grid(True, alpha=0.3)537538# Efficiency curve539eta = 0.85 * (1 - ((Q_sys - 0.025)/0.025)**2)540eta = np.maximum(eta, 0)541ax2.plot(Q_sys*1000, eta*100, 'g-', linewidth=2, label='Efficiency')542ax2.plot(Q_sys*1000, NPSH_r, 'm--', linewidth=2, label='NPSH$_r$')543ax2.axvline(Q_op*1000, color='k', linestyle='--', alpha=0.5)544ax2.set_xlabel('Flow Rate (L/s)')545ax2.set_ylabel('Efficiency (\\%) / NPSH (m)')546ax2.set_title('Pump Performance')547ax2.legend()548ax2.grid(True, alpha=0.3)549550plt.tight_layout()551save_fig('pump_selection.pdf')552553# Calculate pump power554eta_op = 0.85 * (1 - ((Q_op - 0.025)/0.025)**2)555P_hydraulic = rho * 9.81 * Q_op * h_op556P_shaft = P_hydraulic / eta_op557\end{pycode}558559\begin{figure}[H]560\centering561\includegraphics[width=\textwidth]{pump_selection.pdf}562\caption{Pump selection showing operating point and performance characteristics.}563\end{figure}564565Pump power required: $P = \py{f"{P_shaft/1000:.2f}"}$ kW (at $\eta = \py{f"{eta_op*100:.1f}"}$\%)566567\section{Conclusions}568569This analysis demonstrates key aspects of pipe flow:570\begin{enumerate}571\item The Darcy-Weisbach equation provides accurate head loss predictions572\item Friction factors depend on both Reynolds number and relative roughness573\item The Moody diagram visualizes friction factor correlations574\item Minor losses from fittings can be significant in short pipe runs575\item Pipe diameter has a strong effect on pressure drop (varies as $D^{-5}$ for constant Q)576\item Parallel pipe analysis requires iterative solution for flow distribution577\item Pump operating point is determined by intersection of system and pump curves578\end{enumerate}579580\end{document}581582583