fluids-package について
機械・化学エンジニア向けに、流動、圧力損失、ポンプ、熱交換器を計算するPython `fluids`ライブラリのスキルガイドです。非圧縮性、圧縮性、二相流を扱う検証済み相関式を紹介します。
主な機能
- 01管摩擦と圧力損失の計算
- 02ポンプ性能と相似則
- 03圧縮性流れの計算
- 04熱交換器・二相流の機能
- 05流体物性ユーティリティ
- 06検証済みの工学相関式
活用シーン
- 01摩擦係数と配管の損失水頭の計算
- 02ポンプ運転条件の評価
- 03気体流動とチョークの解析
- 04熱交換器の設計・解析
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ soljourner/ claude-engineering-skills --skill fluids-packageインストール後、Claude Code で/fluids-packageを入力して読み込まれたか確認します。
同梱ファイルexamples.pyreference.md
詳細
Fluids パッケージのスキル
概要
fluids ライブラリは、流体の流れに関する問題に取り組む機械・化学エンジニア向けの包括的な Python パッケージです。検証済みの相関式と関数を提供します。
- 管内流れと摩擦係数の計算
- ポンプの選定と性能解析
- 圧縮性流れと非圧縮性流れ
- 熱交換器の設計
- 二相流
- 圧力損失の計算
- 流体の物性
このライブラリには、文献に基づく 100 を超える相関式が実装されており、公開されているテストケースとの広範な照合によって検証されています。
インストール
pip install fluids
最適化ルーチンを含むすべての機能を利用するには、次を実行します。
pip install fluids[complete]
主なモジュール
fluids.core
コアユーティリティと次元解析関数です。
fluids.friction
次の機能を含む、管内流れの摩擦係数の計算です。
- Darcy-Weisbach 方程式
- Colebrook-White 相関式
- Moody 線図の実装
- 乱流と層流の流動領域
fluids.pump
ポンプ性能の計算です。
- 相似則
- 比速度
- NPSH の計算
- ポンプ性能曲線と効率
fluids.compressible
圧縮性流れの計算です。
- マッハ数の関係式
- チョーク流れの条件
- 等エントロピー流れ
- 垂直衝撃波
fluids.fittings
バルブ、継手、配管部品による圧力損失です。
エンジニアリング上の背景を踏まえた一般的な関数
レイノルズ数の計算
レイノルズ数(Re)は流動領域を判定するもので、すべての管内流れ計算の基本です。
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
摩擦係数(Darcy-Weisbach)
摩擦係数(f)は、次の Darcy-Weisbach 方程式で使用されます。ΔP = f(L/D)(ρV²/2)
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)
管内の損失水頭
配管システムの圧力損失と損失水頭を計算します。
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")
ポンプの相似則
回転速度や羽根車径が異なる場合のポンプ性能の関係を示します。
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")
比速度の計算
比速度(Ns)はポンプの種類と効率を特徴づけます。
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}")
圧縮性流れ — マッハ数
配管やノズル内の気体流れに使用します。
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
圧縮性流れ — チョーク流れ
ノズルまたはオリフィス内の流れがチョークしているかどうかを判定します。
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")
エンジニアリングの実例
例 1:ポンプの選定とシステム曲線
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 ✓
例 2:ポンプの並列構成
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 ✓
例 3:摩擦係数の検証
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! ✓")
例 4:管内の圧縮性流れ
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")
ベストプラクティス
- 摩擦係数の相関式を選ぶ前に、必ずレイノルズ数を確認してください
- 既知のテストケースまたはハンドブックの値と照合して、結果を検証してください
- 単位を統一してください — fluids では全体を通して SI 単位を使用します
- ポンプを選定する際は、安全率を考慮してください(通常は 10~15% の余裕)
- 物理的な限界を確認してください — 非圧縮性の仮定ではマッハ数が 0.3 未満であることを確認します
- 文献(Moody、Crane TP-410)に基づく適切な粗さの値を使用してください
一般的な管の粗さの値
| 材質 | 粗さ ε (m) |
|---|---|
| 引抜き管 | 0.0000015 |
| 商用鋼 | 0.000045 |
| 亜鉛めっき鉄 | 0.00015 |
| 鋳鉄 | 0.00026 |
| コンクリート | 0.0003 to 0.003 |
| リベット接合鋼 | 0.0009 to 0.009 |
トラブルシューティング
問題:摩擦係数が収束しない
- 原因:レイノルズ数または ε/D 比が無効です
- 解決策:Re > 0 かつ 0 ≤ ε/D < 0.5 であることを確認します
問題:ポンプ性能曲線がシステム曲線と交差しない
- 原因:ポンプの容量が不足しているか、過大です
- 解決策:相似則を使ってポンプ速度を調整するか、別のポンプを選択します
問題:圧縮性流れの結果が現実的でない
- 原因:非圧縮性流れの方程式を使用している一方で、マッハ数が 0.3 を超えています
- 解決策:fluids.compressible の圧縮性流れ関数を使用します
参考資料
- Crane Technical Paper 410 (TP-410):「バルブ、継手、配管内の流体の流れ」
- Moody, L.F. (1944):「管内流れの摩擦係数」
- Colebrook, C.F. (1939):「管内の乱流」
- Karassik's Pump Handbook(第 4 版)
- GPSA Engineering Data Book(第 14 版)
さらに詳しく
- 公式ドキュメント:https://fluids.readthedocs.io/
- ソースコード:https://github.com/CalebBell/fluids
- 化学工学設計ライブラリ:https://chemicals.readthedocs.io/
コメント
Markdown 対応