Translated from the author's Korean original. Read the original (한국어)
Poiseuille Flow: Analytical Solution Derivation and Finite Difference Validation
The ~2.0 in the order column is not the log ratio of those five L2 values. On a quadratic, the second-order truncation error is identically zero.
Two plates, gap . Pressure drops only in . Fully developed means and . A round pipe carries the same name, Poiseuille flow, but the formulas below are the plane channel. If a code misses this parabola, the viscous term or the no-slip wall is wrong.
Move the −dp/dx or μ slider and only the printed changes. The drawn curve does not.
압력 구배가 커지거나 점성이 작아지면 포물선이 가팔라진다. Re > 2300 부근부터는 이 해석해가 무의미 — 천이 영역.
The curve on the canvas is . The Re slider only shifts the corner label. With , the peak readout is the −dp/dx value divided by .
Problem Setup#
Geometry and Boundary Conditions#
Consider a fully developed laminar flow between two infinite parallel plates.
- Channel half-width: (plates are located at )
- Flow direction: (assumed infinitely long)
- Boundary conditions: no-slip at both walls
- Driving force: constant pressure gradient ( is a constant)
Governing Equation#
Since the flow is fully developed, and . The -direction Navier–Stokes equation is:
Applying the fully developed conditions (, ):
Analytical Derivation#
Step 1: Simplify to an ODE#
Step 2: First Integration#
Step 3: Second Integration#
Step 4: Apply Boundary Conditions#
:
:
(1) (2): (Symmetry)
(1) (2):
Final Analytical Solution#
Maximum velocity at the channel center ():
Physical Interpretation#
Velocity Profile#
The analytical solution is a parabolic distribution. Wall friction is transmitted uniformly throughout the flow cross-section, resulting in a maximum at the center and zero at the walls.
The dimensionless velocity is a universal profile, independent of the channel half-width or the viscosity .
Wall Shear Stress#
(Magnitude: ) The larger the pressure gradient and the wider the channel, the greater the wall friction.
Volumetric Flow Rate#
This is known as the 2D version of the Hagen-Poiseuille law. Since the flow rate is proportional to , doubling the channel width increases the flow rate eightfold.
Code defaults give and . Divide by the height and the mean is , two thirds of the peak. Integrate from to and divide by : the same . and cancel.
Double only : grows by 4 (), by 8 (), wall stress by 2. Treat the stress like the flow-rate ratio and the wall value is four times too high. The laminar pipe that locks the kinetic-energy factor at 2.0000 is the coefficient in front of velocity head.
Visualizing the Analytical Solution with Python#
import numpy as np
import matplotlib.pyplot as plt
# Parameters
h = 1.0 # Channel half-width [m]
G = 1.0 # Pressure gradient [Pa/m]
mu = 1.0 # Dynamic viscosity [Pa·s]
# Grid
y = np.linspace(-h, h, 400)
u_exact = G / (2 * mu) * (h**2 - y**2)
u_max = G * h**2 / (2 * mu)
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
# Velocity Profile (Horizontal)
axes[0].plot(u_exact / u_max, y / h, "k-", lw=2)
axes[0].fill_betweenx(y / h, u_exact / u_max, alpha=0.15)
axes[0].axvline(0, color="gray", lw=0.8, ls="--")
axes[0].set_xlabel(r"$u / u_{\max}$")
axes[0].set_ylabel(r"$y / h$")
axes[0].set_title("Poiseuille Velocity Profile")
axes[0].set_xlim(-0.05, 1.1)
# Shear Stress Distribution
tau = mu * np.gradient(u_exact, y)
axes[1].plot(tau / G / h, y / h, "r-", lw=2, label=r"$\tau / \tau_w$")
axes[1].axvline(0, color="gray", lw=0.8, ls="--")
axes[1].set_xlabel(r"$\tau / \tau_w$")
axes[1].set_ylabel(r"$y / h$")
axes[1].set_title("Shear Stress Distribution (Linear)")
axes[1].legend()
plt.tight_layout()
plt.savefig("poiseuille_profile.png", dpi=150)
plt.show()Numerical Validation with Finite Difference Method#
We discretize using a second-order central difference scheme. On a uniform grid :
Boundary conditions: .
Writing this as a tridiagonal system of linear equations:
Python Implementation#
import numpy as np
def solve_poiseuille_fd(N, h=1.0, G=1.0, mu=1.0):
"""
N : Number of internal grid points (excluding boundaries)
returns (y, u_num, u_exact, L2_error)
"""
dy = 2 * h / (N + 1)
y_inner = np.linspace(-h + dy, h - dy, N)
# Tridiagonal coefficient matrix
diag = -2 * np.ones(N)
upper = np.ones(N - 1)
lower = np.ones(N - 1)
A = (np.diag(diag) + np.diag(upper, k=1) + np.diag(lower, k=-1))
rhs = -G * dy**2 / mu * np.ones(N)
u_num = np.linalg.solve(A, rhs)
# Full grid including boundaries
y_full = np.concatenate([[-h], y_inner, [h]])
u_full = np.concatenate([[0.0], u_num, [0.0]])
u_exact = G / (2 * mu) * (h**2 - y_full**2)
L2 = np.sqrt(np.mean((u_full - u_exact)**2))
return y_full, u_full, u_exact, L2
# Grid convergence test
Ns = [4, 8, 16, 32, 64, 128, 256]
errors = []
for N in Ns:
_, _, _, err = solve_poiseuille_fd(N)
errors.append(err)
# Convergence order
for i in range(1, len(Ns)):
ratio = errors[i-1] / errors[i]
order = np.log2(ratio)
print(f"N={Ns[i]:4d} L2={errors[i]:.3e} Convergence Order={order:.2f}")Convergence Results#
| Error | Convergence Order | ||
|---|---|---|---|
| 4 | 0.4000 | 2.78e-16 | — |
| 8 | 0.2222 | 1.67e-16 | ~2.0 |
| 16 | 0.1176 | 2.22e-16 | ~2.0 |
| 32 | 0.0606 | 2.78e-16 | ~2.0 |
| 64 | 0.0308 | 2.22e-16 | ~2.0 |
Note: Since Poiseuille flow is a quadratic polynomial, the second-order central difference scheme yields results at the level of machine precision. The actual error does not scale with but saturates at the floating-point rounding error level.
At low the parabola already sits on the formula. That is enough to see whether the viscous term is alive. The order column cannot make that call.
The discretization line writes . The table does not. At the spacings are 0.4000, 0.2222, 0.1176, 0.0606, 0.0308. With those equal : , , , , . Both walls are dropped from the unknowns, so the spacing is .
The five entries are , , , , . Successive base-2 logs are about 0.7, then negative, negative, then about 0.3. Not ~2.0. A quadratic in has zero third derivative, so the second-order truncation error is zero. This column does not measure order.
Comparison Plot of Results#
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6, 5))
colors = plt.cm.viridis(np.linspace(0.2, 0.9, 4))
Ns_plot = [4, 8, 16, 64]
for N, c in zip(Ns_plot, colors):
y, u_num, _, _ = solve_poiseuille_fd(N)[:3]
_, _, u_exact, _ = solve_poiseuille_fd(N)
ax.plot(u_num, y, "o--", color=c, ms=4, label=f"FD N={N}")
# Analytical solution
y_fine = np.linspace(-1, 1, 400)
ax.plot(0.5 * (1 - y_fine**2), y_fine, "k-", lw=2, label="Analytical Solution")
ax.set_xlabel(r"$u$ (Non-dimensional)")
ax.set_ylabel(r"$y/h$")
ax.set_title("Comparison: FD vs Analytical Solution")
ax.legend(fontsize=9)
plt.tight_layout()
plt.savefig("poiseuille_fd_vs_exact.png", dpi=150)
plt.show()OpenFOAM Setup Hints#
When setting up Poiseuille flow with OpenFOAM's icoFoam, the key parameters are:
0/U — Velocity Boundary Conditions#
boundaryField
{
walls
{
type noSlip; // No-slip at wall
}
inlet
{
type fixedValue;
value uniform (1 0 0); // Or parabolicVelocity
}
outlet
{
type zeroGradient;
}
}0/p — Pressure Boundary Conditions#
boundaryField
{
inlet { type fixedValue; value uniform 1; }
outlet { type fixedValue; value uniform 0; }
walls { type zeroGradient; }
}constant/transportProperties#
nu nu [ 0 2 -1 0 0 0 0 ] 0.01; // Adjust kinematic viscosityEntrance length and centerline speed#
- Fully Developed Condition: The channel length must be sufficiently longer than the entrance development length ().
- Grid Independence: A grid count of 16 or more in the -direction ensures second-order accuracy.
- Validation Metrics: Compare the centerline velocity and wall shear stress .
Stop reading the order column once L2 is 1e-16?#
At , is already . Pushing the grid to 64 only jiggles that column inside the band. The printed ~2.0 did not come from those ratios. On a quadratic the central scheme has zero truncation error, so signing off the order from this table is the wrong call. Whether is alive shows up in the centerline speed and the wall stress.
Check and . Order that actually splits lives on a solution with a discontinuity. The same code reporting 0.79 and 2.00 at once is where that column stops meaning the scheme order. Stuck on roundoff, a finer grid here still does not produce an order.
References
- Batchelor, G. K. An Introduction to Fluid Dynamics. Cambridge, 1967.
- Ferziger, J. H., Perić, M. Computational Methods for Fluid Dynamics. Springer, 2002.
- OpenFOAM Documentation — icoFoam tutorial: cavity
Related
Share if you found it helpful.