Skip to content
All Skills

Fluids Package

Pipe flow, pump sizing, friction factor, and compressible flow calculations

Science & Simulation|v1|Updated 7/14/2026|GitHub source
MCP get_skill({ skillId: "fluids-package-aaba2061" })

Use this skill with your agent

Create a free account and connect via MCP

Get Started Free
# Fluids Package Skill

## Overview

The `fluids` library is a comprehensive Python package for mechanical and chemical engineers working with fluid flow problems. It provides validated correlations and functions for:

- Pipe flow and friction factor calculations
- Pump sizing and performance analysis
- Compressible and incompressible flow
- Heat exchanger design
- Two-phase flow
- Pressure drop calculations
- Fluid properties

The library implements over 100 correlations from the literature with extensive validation against published test cases.

## Installation

```bash
pip install fluids
```

For full functionality including optimization routines:

```bash
pip install fluids[complete]
```

## Key Modules

### fluids.core
Core utilities and dimensional analysis functions.

### fluids.friction
Friction factor calculations for pipe flow including:
- Darcy-Weisbach equation
- Colebrook-White correlation
- Moody diagram implementations
- Turbulent and laminar flow regimes

### fluids.pump
Pump performance calculations:
- Affinity laws
- Specific speed
- NPSH calculations
- Pump curves and efficiency

### fluids.compressible
Compressible flow calculations:
- Mach number relationships
- Choked flow conditions
- Isentropic flow
- Normal shock waves

### fluids.fittings
Pressure drop through valves, fittings, and pipe components.

## Common Functions with Engineering Context

### Reynolds Number Calculation

The Reynolds number (Re) determines flow regime and is fundamental to all pipe flow calculations.

```python
from fluids.core import Reynolds

# For pipe flow: Re = ρVD/μ
Re = Reynolds(V=2.5, D=0.05, rho=1000, mu=0.001)
# Result: 125000 (turbulent flow)

# Interpretation:
# Re < 2300: Laminar flow
# 2300 < Re < 4000: Transition
# Re > 4000: Turbulent flow
```

### Friction Factor (Darcy-Weisbach)

The friction factor (f) is used in the Darcy-Weisbach equation: ΔP = f(L/D)(ρV²/2)

```python
from fluids.friction import friction_factor

# Colebrook-White correlation (implicit, most accurate)
f = friction_factor(Re=125000, eD=0.0001)  # eD = roughness/diameter
# Result: ~0.0178

# Moody correlation (explicit approximation)
from fluids.friction import friction_factor_Moody
f_moody = friction_factor_Moody(Re=125000, eD=0.0001)

# For laminar flow (Re < 2300):
f_laminar = friction_factor(Re=1500, eD=0.0001)
# Result: 0.0427 (f = 64/Re)
```

### Head Loss in Pipes

Calculate pressure drop and head loss in piping systems.

```python
from fluids.friction import friction_factor, head_from_P
from fluids.core import Reynolds

# Given: Water flow through steel pipe
D = 0.1  # m, pipe diameter
L = 100  # m, pipe length
V = 2.0  # m/s, velocity
rho = 1000  # kg/m³, density
mu = 0.001  # Pa·s, viscosity
epsilon = 0.000045  # m, roughness (steel)

# Step 1: Calculate Reynolds number
Re = Reynolds(V=V, D=D, rho=rho, mu=mu)

# Step 2: Calculate friction factor
eD = epsilon / D
f = friction_factor(Re=Re, eD=eD)

# Step 3: Calculate pressure drop
# Darcy-Weisbach: ΔP = f(L/D)(ρV²/2)
dP = f * (L/D) * (rho * V**2 / 2)

# Step 4: Convert to head loss
h_loss = head_from_P(dP, rho)  # meters of fluid

print(f"Reynolds: {Re:.0f}")
print(f"Friction factor: {f:.5f}")
print(f"Pressure drop: {dP:.0f} Pa")
print(f"Head loss: {h_loss:.2f} m")
```

### Pump Affinity Laws

Relate pump performance at different speeds and impeller diameters.

```python
from fluids.pump import affinity_law_volume, affinity_law_head, affinity_law_power

# Original pump operating point
Q1 = 100  # m³/h, flow rate
H1 = 50   # m, head
P1 = 20   # kW, power
N1 = 1450 # rpm, speed
D1 = 0.3  # m, impeller diameter

# New speed
N2 = 1750  # rpm

# Affinity laws (constant impeller diameter):
# Q2/Q1 = N2/N1
# H2/H1 = (N2/N1)²
# P2/P1 = (N2/N1)³

Q2 = affinity_law_volume(Q1, N1, N2)
H2 = affinity_law_head(H1, N1, N2)
P2 = affinity_law_power(P1, N1, N2)

print(f"New flow: {Q2:.1f} m³/h")
print(f"New head: {H2:.1f} m")
print(f"New power: {P2:.1f} kW")
```

### Specific Speed Calculations

Specific speed (Ns) characterizes pump type and efficiency.

```python
from fluids.pump import specific_speed

# Pump operating conditions
Q = 0.05  # m³/s, flow rate
H = 40    # m, head
N = 1450  # rpm, rotational speed

# Calculate specific speed (dimensionless)
Ns = specific_speed(Q, H, N)

# Interpretation:
# Ns < 0.5: Centrifugal (radial flow)
# 0.5 < Ns < 1.0: Francis (mixed flow)
# 1.0 < Ns < 4.0: Propeller (axial flow)

print(f"Specific speed: {Ns:.2f}")
if Ns < 0.5:
    pump_type = "Centrifugal (radial flow)"
elif Ns < 1.0:
    pump_type = "Francis (mixed flow)"
else:
    pump_type = "Propeller (axial flow)"
print(f"Recommended pump type: {pump_type}")
```

### Compressible Flow - Mach Number

For gas flow in pipes and nozzles.

```python
from fluids.compressible import Mach

# Calculate Mach number from velocity
V = 200  # m/s, velocity
c = 340  # m/s, speed of sound in air at 15°C

Ma = Mach(V, c)
# Result: 0.588

# Flow classification:
# Ma < 0.3: Incompressible
# 0.3 < Ma < 0.8: Subsonic
# 0.8 < Ma < 1.2: Transonic
# Ma > 1.2: Supersonic
```

### Compressible Flow - Choked Flow

Determine if flow is choked in a nozzle or orifice.

```python
from fluids.compressible import P_critical_flow

# Gas properties
P_upstream = 500000  # Pa, upstream pressure
k = 1.4  # heat capacity ratio (air)

# Critical pressure for choked flow
P_crit = P_critical_flow(P=P_upstream, k=k)
# Result: ~264,000 Pa

# If downstream pressure < P_crit, flow is choked
P_downstream = 200000  # Pa
if P_downstream < P_crit:
    print("Flow is choked - mass flow is at maximum")
    print(f"Critical pressure: {P_crit:.0f} Pa")
else:
    print("Flow is not choked")
```

## Complete Engineering Examples

### Example 1: Pump Selection and System Curve

```python
import numpy as np
from fluids.friction import friction_factor
from fluids.core import Reynolds
import matplotlib.pyplot as plt

def system_curve(Q_range, static_head, pipe_specs):
    """
    Calculate system head curve for a piping system.

    Parameters:
    -----------
    Q_range : array, flow rates (m³/s)
    static_head : float, static lift (m)
    pipe_specs : dict with keys:
        - L: pipe length (m)
        - D: pipe diameter (m)
        - epsilon: roughness (m)
        - rho: fluid density (kg/m³)
        - mu: fluid viscosity (Pa·s)

    Returns:
    --------
    H_system : array, required head at each flow rate (m)
    """
    L = pipe_specs['L']
    D = pipe_specs['D']
    rho = pipe_specs['rho']
    mu = pipe_specs['mu']
    epsilon = pipe_specs['epsilon']

    # Calculate cross-sectional area
    A = np.pi * D**2 / 4

    H_system = np.zeros_like(Q_range)

    for i, Q in enumerate(Q_range):
        if Q == 0:
            H_system[i] = static_head
            continue

        # Calculate velocity
        V = Q / A

        # Reynolds number
        Re = Reynolds(V=V, D=D, rho=rho, mu=mu)

        # Friction factor
        eD = epsilon / D
        f = friction_factor(Re=Re, eD=eD)

        # Friction head loss (Darcy-Weisbach)
        h_friction = f * (L/D) * (V**2 / (2*9.81))

        # Total system head
        H_system[i] = static_head + h_friction

    return H_system

# Define system
pipe_specs = {
    'L': 200,  # m
    'D': 0.15,  # m
    'epsilon': 0.000045,  # m (steel)
    'rho': 1000,  # kg/m³
    'mu': 0.001  # Pa·s
}
static_head = 30  # m

# Generate system curve
Q_range = np.linspace(0, 0.1, 50)  # m³/s
H_system = system_curve(Q_range, static_head, pipe_specs)

# Example pump curve (quadratic fit)
# H = H0 - A*Q - B*Q²
H0 = 80  # m, shutoff head
A = 200  # head loss coefficient
B = 3000  # quadratic coefficient
H_pump = H0 - A*Q_range - B*Q_range**2

# Find operating point (intersection)
idx = np.argmin(np.abs(H_pump - H_system))
Q_op = Q_range[idx]
H_op = H_system[idx]

print(f"Operating Point:")
print(f"  Flow rate: {Q_op*3600:.1f} m³/h ({Q_op:.4f} m³/s)")
print(f"  Head: {H_op:.1f} m")

# Verification: At Q=0.05 m³/s
# V = Q/A = 0.05/(π*0.15²/4) = 2.83 m/s
# Re = 1000*2.83*0.15/0.001 = 424,500 (turbulent)
# f ≈ 0.0175 (from Moody chart)
# h_f = 0.0175*(200/0.15)*(2.83²/(2*9.81)) = 9.5 m
# H_total = 30 + 9.5 = 39.5 m ✓
```

### Example 2: Parallel Pump Configuration

```python
from fluids.pump import affinity_law_volume, affinity_law_head

def parallel_pumps(Q_total, n_pumps, single_pump_curve):
    """
    Calculate operating point for parallel pump configuration.

    For pumps in parallel:
    - Flow rates add: Q_total = n * Q_single
    - Head remains the same: H_total = H_single
    """
    # Single pump flow rate
    Q_single = Q_total / n_pumps

    # Head from single pump curve
    H = single_pump_curve(Q_single)

    return Q_single, H

# Single pump curve: H = 60 - 500*Q² (simplified)
def pump_curve(Q):
    return 60 - 500*Q**2

# System requires 150 m³/h at 40 m head
Q_required = 150/3600  # m³/s
n_pumps = 2

Q_single, H_operating = parallel_pumps(Q_required, n_pumps, pump_curve)

print(f"Parallel Pump Configuration ({n_pumps} pumps):")
print(f"  Total flow: {Q_required*3600:.1f} m³/h")
print(f"  Flow per pump: {Q_single*3600:.1f} m³/h")
print(f"  Operating head: {H_operating:.1f} m")

# Verification:
# Each pump delivers 75 m³/h (0.0208 m³/s)
# H = 60 - 500*(0.0208)² = 60 - 0.22 = 59.8 m ✓
```

### Example 3: Friction Factor Validation

```python
from fluids.friction import friction_factor, friction_factor_laminar

# Test Case 1: Laminar Flow (Poiseuille)
# Analytical solution: f = 64/Re
Re_laminar = 1000
f_calculated = friction_factor(Re=Re_laminar, eD=0)
f_analytical = 64/Re_laminar

print("Test 1: Laminar Flow")
print(f"  Re = {Re_laminar}")
print(f"  f (calculated) = {f_calculated:.6f}")
print(f"  f (analytical) = {f_analytical:.6f}")
print(f"  Error = {abs(f_calculated - f_analytical):.9f}")
assert abs(f_calculated - f_analytical) < 1e-9, "Laminar flow test failed"
print("  ✓ PASSED\n")

# Test Case 2: Turbulent Flow - Smooth Pipe
# From Moody diagram: Re=1e5, smooth pipe → f ≈ 0.0183
Re_turbulent = 1e5
f_smooth = friction_factor(Re=Re_turbulent, eD=0)

print("Test 2: Turbulent Flow (Smooth Pipe)")
print(f"  Re = {Re_turbulent:.0f}")
print(f"  f (calculated) = {f_smooth:.6f}")
print(f"  f (Moody chart) ≈ 0.0183")
print(f"  Error = {abs(f_smooth - 0.0183):.6f}")
assert abs(f_smooth - 0.0183) < 0.0005, "Smooth pipe test failed"
print("  ✓ PASSED\n")

# Test Case 3: Turbulent Flow - Rough Pipe
# Commercial steel: ε/D = 0.0002, Re = 1e6 → f ≈ 0.0144
Re_rough = 1e6
eD_rough = 0.0002
f_rough = friction_factor(Re=Re_rough, eD=eD_rough)

print("Test 3: Turbulent Flow (Rough Pipe)")
print(f"  Re = {Re_rough:.0f}")
print(f"  ε/D = {eD_rough}")
print(f"  f (calculated) = {f_rough:.6f}")
print(f"  f (Moody chart) ≈ 0.0144")
print(f"  Error = {abs(f_rough - 0.0144):.6f}")
assert abs(f_rough - 0.0144) < 0.0005, "Rough pipe test failed"
print("  ✓ PASSED\n")

# Test Case 4: From Crane TP-410 (Standard reference)
# Example 4-9: Water in 6-inch Schedule 40 pipe
D = 0.1541  # m (6-inch Schedule 40 ID)
V = 3.05  # m/s
rho = 998  # kg/m³
mu = 0.001  # Pa·s
epsilon = 0.000045  # m (steel)

Re_crane = Reynolds(V=V, D=D, rho=rho, mu=mu)
eD_crane = epsilon/D
f_crane = friction_factor(Re=Re_crane, eD=eD_crane)

# Crane TP-410 gives f ≈ 0.0172
print("Test 4: Crane TP-410 Example 4-9")
print(f"  Re = {Re_crane:.0f}")
print(f"  ε/D = {eD_crane:.6f}")
print(f"  f (calculated) = {f_crane:.6f}")
print(f"  f (Crane TP-410) ≈ 0.0172")
print(f"  Error = {abs(f_crane - 0.0172):.6f}")
assert abs(f_crane - 0.0172) < 0.0003, "Crane TP-410 test failed"
print("  ✓ PASSED\n")

print("All friction factor tests passed! ✓")
```

### Example 4: Compressible Flow in Pipe

```python
from fluids.compressible import isothermal_gas

# Gas pipeline calculation
# Problem: Natural gas (methane) pipeline
P1 = 5e6  # Pa, inlet pressure
T = 288.15  # K, temperature (15°C)
L = 50000  # m, pipeline length (50 km)
D = 0.5  # m, diameter
m = 10  # kg/s, mass flow rate
MW = 16.04  # g/mol, molecular weight (CH4)
k = 1.31  # heat capacity ratio

# Calculate outlet pressure using isothermal flow
# This accounts for friction and compressibility
from fluids.compressible import isothermal_gas
P2 = isothermal_gas(rho=None, P1=P1, P2=None, L=L, D=D, m=m,
                    T=T, Z=1, fd=0.012)  # Assuming f=0.012

print("Gas Pipeline Calculation:")
print(f"  Inlet pressure: {P1/1e6:.2f} MPa")
print(f"  Outlet pressure: {P2/1e6:.2f} MPa")
print(f"  Pressure drop: {(P1-P2)/1e6:.2f} MPa")
print(f"  Length: {L/1000:.0f} km")
print(f"  Mass flow: {m:.1f} kg/s")
```

## Best Practices

1. **Always check Reynolds number** before selecting friction factor correlation
2. **Validate results** against known test cases or handbook values
3. **Use consistent units** - fluids uses SI units throughout
4. **Consider safety factors** when sizing pumps (typically 10-15% margin)
5. **Check physical limits** - verify Mach number < 0.3 for incompressible assumption
6. **Use appropriate roughness values** from literature (Moody, Crane TP-410)

## Common Pipe Roughness Values

| Material | Roughness ε (m) |
|----------|----------------|
| Drawn tubing | 0.0000015 |
| Commercial steel | 0.000045 |
| Galvanized iron | 0.00015 |
| Cast iron | 0.00026 |
| Concrete | 0.0003 to 0.003 |
| Riveted steel | 0.0009 to 0.009 |

## Troubleshooting

### Issue: Friction factor doesn't converge
- **Cause**: Invalid Reynolds number or ε/D ratio
- **Solution**: Check that Re > 0 and 0 ≤ ε/D < 0.5

### Issue: Pump curves don't intersect system curve
- **Cause**: Pump undersized or oversized
- **Solution**: Adjust pump speed using affinity laws or select different pump

### Issue: Compressible flow results unrealistic
- **Cause**: Mach number > 0.3 but using incompressible equations
- **Solution**: Use compressible flow functions from fluids.compressible

## References

- Crane Technical Paper 410 (TP-410): "Flow of Fluids Through Valves, Fittings, and Pipe"
- Moody, L.F. (1944): "Friction factors for pipe flow"
- Colebrook, C.F. (1939): "Turbulent flow in pipes"
- Karassik's Pump Handbook (4th Edition)
- GPSA Engineering Data Book (14th Edition)

## Further Reading

- Official documentation: https://fluids.readthedocs.io/
- Source code: https://github.com/CalebBell/fluids
- Chemical Engineering Design Library: https://chemicals.readthedocs.io/
#broad-capability#engineering#fluid-dynamics#thermodynamics#structural-analysis#scipy#sympy#cfd#computational#fluid#dynamicspython

Related Skills

More skills in Science & Simulation

Adaptyv

Cloud laboratory platform for automated protein testing and validation. Use when designing proteins and needing experimental validation including binding assays, expression testing, thermostability measurements, enzyme activity assays, or protein sequence optimization. Also use for submitting experiments via API, tracking experiment status, downloading results, optimizing protein sequences for better expression using computational tools (NetSolP, SoluProt, SolubleMPNN, ESM), or managing protein design workflows with wet-lab validation.

#broad-capability#creativeApache-2.0

AI Analyzer

AI驱动的综合健康分析系统,整合多维度健康数据、识别异常模式、预测健康风险、提供个性化建议。支持智能问答和AI健康报告生成。

#work-life#productivityMIT

Ansys Simulation

Automate ANSYS Fluent CFD simulations via Python scripting and journal files

#broad-capability#engineeringMIT

Astropy

Comprehensive Python library for astronomy and astrophysics. This skill should be used when working with astronomical data including celestial coordinates, physical units, FITS files, cosmological calculations, time systems, tables, world coordinate systems (WCS), and astronomical data analysis. Use when tasks involve coordinate transformations, unit conversions, FITS file manipulation, cosmological distance calculations, time scale conversions, or astronomical data processing.

#broad-capability#creativeApache-2.0

Bioservices

Unified Python interface to 40+ bioinformatics services. Use when querying multiple databases (UniProt, KEGG, ChEMBL, Reactome) in a single workflow with consistent API. Best for cross-database analysis, ID mapping across services. For quick single-database lookups use gget; for sequence/file manipulation use biopython.

#k-dense-ai-claude-scientific-skills#bioinformaticsMIT

Bom

BOM (Bill of Materials) management for electronics projects — the primary orchestrator skill that coordinates DigiKey, Mouser, LCSC, element14, JLCPCB, PCBWay, and KiCad skills into a unified workflow. Create, update, and maintain BOMs with part numbers, costs, quantities stored as KiCad symbol properties. ALWAYS trigger this skill for any task involving component sourcing, pricing, ordering, distributor searches, BOM export, or fabrication preparation — even if the user names a specific distributor or fab house (e.g. "search DigiKey for...", "generate JLCPCB BOM", "order from Mouser"). This skill decides which distributor/fab skills to invoke and in what order. Also trigger on phrases like "what parts do I need", "order components", "how much will this cost", "export for JLCPCB", "find parts for this board", "cost estimate", "compare pricing", or "check stock".

#kicad#electronicsMIT