mcpField
T
thermo-package

thermo-package

github.com/soljourner其他9541 次安装51 周前更新
代码仓库

关于 thermo-package

thermo-package 是面向工程师的技能,介绍如何用 Python 的 thermo 库计算化学性质与相平衡。内容侧重泵和工艺流体分析,涵盖温度相关性质、混合物及闪蒸计算。

主要功能

  1. 01纯组分性质计算
  2. 02混合物与物流计算
  3. 03VLE 与闪蒸计算
  4. 04包含 PR 和 SRK 的状态方程
  5. 05面向泵的热力与相态分析

适用场景

  1. 01按温度相关黏度修正泵计算
  2. 02估算 NPSH 与汽蚀风险
  3. 03分析混合物及多相泵送物流

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/soljourner/claude-engineering-skills --skill thermo-package

安装后在 Claude Code 中输入/thermo-package确认已加载。

附带文件examples.pyreference.md

详细介绍

Thermo 软件包技能

概述

thermo 库是一个功能全面的 Python 软件包,面向处理热力学性质和相平衡的化学与机械工程师。它提供经过验证的关联式,用于计算:

  • 纯组分热力学性质
  • 混合物性质
  • 气液平衡(VLE)
  • 焓、熵和热容
  • 随温度变化的流体性质
  • 状态方程(EOS)实现
  • 混合物相平衡

该库包含丰富的化学数据库,并实现了 DIPPR、NIST 和文献来源中的行业标准关联式。对于涉及随温度变化的性质、混合物和多相流的泵应用而言,它必不可少。

安装

pip install thermo chemicals

chemicals 软件包是必需的依赖项,提供化学数据库和纯组分性质关联式。

主要模块

thermo.chemical

纯组分性质接口,包括:

  • 随温度变化的黏度、密度和热导率
  • 蒸气压和相态行为
  • 热容(Cp、Cv)
  • 焓和熵
thermo.mixture

混合物性质计算:

  • 按组成加权的性质
  • EOS 混合规则
  • 偏摩尔性质
  • 过剩性质
thermo.stream

工艺流体计算:

  • 质量和能量衡算
  • 闪蒸计算(VLE)
  • 相分率确定
  • 流体的焓
thermo.eos

状态方程实现:

  • Peng-Robinson(PR)
  • Soave-Redlich-Kwong(SRK)
  • 理想气体定律
  • 立方型状态方程

泵工程核心能力

1. 随温度变化的黏度

对于泵在不同运行温度范围内的性能至关重要。

from thermo.chemical import Chemical

# Water viscosity variation with temperature
water = Chemical('water', T=298.15, P=101325)  # 25°C, 1 atm

# At different temperatures
temps = [20, 40, 60, 80, 100]  # °C
for T_c in temps:
    water.T = T_c + 273.15
    print(f"T = {T_c}°C: μ = {water.mu*1000:.4f} cP, ρ = {water.rho:.1f} kg/m³")

# Output demonstrates viscosity decreasing with temperature:
# T = 20°C: μ = 1.0016 cP, ρ = 998.2 kg/m³
# T = 40°C: μ = 0.6529 cP, ρ = 992.2 kg/m³
# T = 60°C: μ = 0.4665 cP, ρ = 983.2 kg/m³
2. 温度变化下的泵功率修正

在不同温度下泵送时,考虑黏度和密度变化。

from thermo.chemical import Chemical

def pump_power_correction(fluid_name, T_design, T_actual, Q, H, eta=0.75):
    """
    Calculate pump power at actual temperature vs design temperature.

    Parameters:
    -----------
    fluid_name : str, chemical name
    T_design : float, design temperature (K)
    T_actual : float, actual temperature (K)
    Q : float, flow rate (m³/s)
    H : float, head (m)
    eta : float, pump efficiency

    Returns:
    --------
    Power correction factor and actual power required
    """
    # Properties at design temperature
    fluid_design = Chemical(fluid_name, T=T_design, P=101325)
    rho_design = fluid_design.rho
    mu_design = fluid_design.mu

    # Properties at actual temperature
    fluid_actual = Chemical(fluid_name, T=T_actual, P=101325)
    rho_actual = fluid_actual.rho
    mu_actual = fluid_actual.mu

    # Power calculation: P = ρ*g*Q*H/η
    g = 9.81  # m/s²
    P_design = rho_design * g * Q * H / eta
    P_actual = rho_actual * g * Q * H / eta

    # Viscosity affects efficiency (simplified)
    # Higher viscosity reduces efficiency
    eta_correction = (mu_design / mu_actual) ** 0.1  # Empirical
    eta_actual = eta * eta_correction
    P_actual_corrected = rho_actual * g * Q * H / eta_actual

    return {
        'P_design': P_design / 1000,  # kW
        'P_actual': P_actual / 1000,  # kW
        'P_corrected': P_actual_corrected / 1000,  # kW
        'rho_ratio': rho_actual / rho_design,
        'mu_ratio': mu_actual / mu_design,
        'eta_correction': eta_correction
    }

# Example: Pumping water at elevated temperature
result = pump_power_correction('water', T_design=298.15, T_actual=353.15,
                                Q=0.05, H=50, eta=0.75)

print(f"Design power: {result['P_design']:.2f} kW")
print(f"Actual power (density only): {result['P_actual']:.2f} kW")
print(f"Actual power (with efficiency): {result['P_corrected']:.2f} kW")
3. 混合物性质

对于处理混合流体或工艺流体的泵至关重要。

from thermo.mixture import Mixture

# Ethanol-water mixture (common in chemical processing)
mixture = Mixture(['ethanol', 'water'], ws=[0.3, 0.7], T=298.15, P=101325)

print(f"Mixture density: {mixture.rho:.1f} kg/m³")
print(f"Mixture viscosity: {mixture.mu*1000:.3f} cP")
print(f"Mixture heat capacity: {mixture.Cp:.1f} J/kg·K")

# Compare to pure components
from thermo.chemical import Chemical
ethanol = Chemical('ethanol', T=298.15, P=101325)
water = Chemical('water', T=298.15, P=101325)

print(f"\nPure ethanol: ρ = {ethanol.rho:.1f} kg/m³, μ = {ethanol.mu*1000:.3f} cP")
print(f"Pure water: ρ = {water.rho:.1f} kg/m³, μ = {water.mu*1000:.3f} cP")
4. 蒸气压和 NPSH 计算

确定可用 NPSH 和气蚀风险。

from thermo.chemical import Chemical

def calculate_NPSHa(fluid_name, T, P_suction, z_suction, v_suction):
    """
    Calculate Net Positive Suction Head Available.

    Parameters:
    -----------
    fluid_name : str, chemical name
    T : float, fluid temperature (K)
    P_suction : float, suction pressure (Pa absolute)
    z_suction : float, suction elevation relative to pump (m)
    v_suction : float, velocity at suction (m/s)

    Returns:
    --------
    NPSHa in meters
    """
    fluid = Chemical(fluid_name, T=T, P=P_suction)

    rho = fluid.rho  # kg/m³
    Psat = fluid.Psat  # Vapor pressure, Pa

    g = 9.81  # m/s²

    # NPSHa = (P_suction - Psat)/(ρ*g) + v²/(2g) - z_suction
    pressure_head = (P_suction - Psat) / (rho * g)
    velocity_head = v_suction**2 / (2 * g)

    NPSHa = pressure_head + velocity_head - z_suction

    return {
        'NPSHa': NPSHa,
        'P_suction': P_suction / 1000,  # kPa
        'Psat': Psat / 1000,  # kPa
        'rho': rho,
        'margin': (P_suction - Psat) / 1000  # kPa
    }

# Example: Water at 80°C (elevated temperature)
result = calculate_NPSHa('water', T=353.15, P_suction=150000,
                         z_suction=2.0, v_suction=2.5)

print(f"NPSHa = {result['NPSHa']:.2f} m")
print(f"Suction pressure = {result['P_suction']:.1f} kPa")
print(f"Vapor pressure = {result['Psat']:.1f} kPa")
print(f"Pressure margin = {result['margin']:.1f} kPa")

# Warning if NPSHa is low
if result['NPSHa'] < 3.0:
    print("⚠ WARNING: Low NPSHa - high cavitation risk!")
5. 泵级间焓计算

计算多级泵中的焓升和温升。

from thermo.chemical import Chemical

def pump_temperature_rise(fluid_name, T_inlet, P_inlet, P_outlet, eta):
    """
    Calculate temperature rise due to pump inefficiency.

    Energy not converted to useful work appears as heat in the fluid:
    ΔT = (1-η) * ΔP / (ρ * Cp)

    Parameters:
    -----------
    fluid_name : str
    T_inlet : float, inlet temperature (K)
    P_inlet : float, inlet pressure (Pa)
    P_outlet : float, outlet pressure (Pa)
    eta : float, pump efficiency
    """
    fluid = Chemical(fluid_name, T=T_inlet, P=P_inlet)

    rho = fluid.rho  # kg/m³
    Cp = fluid.Cp  # J/kg·K

    delta_P = P_outlet - P_inlet  # Pa

    # Temperature rise from inefficiency
    delta_T = (1 - eta) * delta_P / (rho * Cp)

    # Recalculate properties at outlet
    T_outlet = T_inlet + delta_T
    fluid_out = Chemical(fluid_name, T=T_outlet, P=P_outlet)

    # Enthalpy change
    H_inlet = fluid.H  # J/kg
    H_outlet = fluid_out.H  # J/kg
    delta_H = H_outlet - H_inlet

    return {
        'T_inlet': T_inlet - 273.15,  # °C
        'T_outlet': T_outlet - 273.15,  # °C
        'delta_T': delta_T,  # K
        'delta_H': delta_H / 1000,  # kJ/kg
        'delta_P': delta_P / 1e6  # MPa
    }

# Example: Multistage boiler feed pump
result = pump_temperature_rise('water', T_inlet=333.15, P_inlet=500000,
                               P_outlet=15000000, eta=0.82)

print(f"Inlet temperature: {result['T_inlet']:.1f} °C")
print(f"Outlet temperature: {result['T_outlet']:.1f} °C")
print(f"Temperature rise: {result['delta_T']:.2f} K")
print(f"Enthalpy rise: {result['delta_H']:.1f} kJ/kg")
print(f"Pressure rise: {result['delta_P']:.1f} MPa")
6. 多相泵的相平衡

确定泵中是否会发生两相流。

from thermo.chemical import Chemical

def check_phase_state(fluid_name, T, P):
    """
    Check if fluid is single-phase or will flash to vapor.
    """
    fluid = Chemical(fluid_name, T=T, P=P)

    Psat = fluid.Psat  # Vapor pressure
    Tsat = fluid.Tb  # Boiling point at 1 atm

    # Determine phase
    if P > Psat:
        phase = "Liquid (subcooled)"
        margin = (P - Psat) / Psat * 100  # % margin
    elif P < Psat:
        phase = "Two-phase or Vapor (FLASHING!)"
        margin = (Psat - P) / P * 100  # % above operating pressure
    else:
        phase = "Saturated liquid"
        margin = 0

    return {
        'phase': phase,
        'T': T - 273.15,
        'P': P / 1000,  # kPa
        'Psat': Psat / 1000,  # kPa
        'margin': margin
    }

# Example: Check if water will flash at pump suction
temps = [40, 60, 80, 100]  # °C
P_suction = 120000  # Pa (1.2 bar absolute)

for T_c in temps:
    result = check_phase_state('water', T=T_c+273.15, P=P_suction)
    print(f"T = {result['T']:.0f}°C, P = {result['P']:.1f} kPa: {result['phase']}")
    if 'subcooled' in result['phase']:
        print(f"  Margin = {result['margin']:.1f}%")
    print()

# Output will show flashing occurs above ~105°C at 1.2 bar

状态方程应用

用于高压泵的 Peng-Robinson EOS
from thermo import ChemicalConstantsPackage, PRMIX, CEOSGas, CEOSLiquid, FlashVL
from thermo.interaction_parameters import IPDB

# High-pressure natural gas mixture
constants = ChemicalConstantsPackage.constants_from_IDs(['methane', 'ethane', 'propane'])

# Operating conditions
T = 298.15  # K
P = 10e6  # Pa (100 bar)
zs = [0.85, 0.10, 0.05]  # Mole fractions

# Peng-Robinson EOS
kijs = IPDB.get_ip_asymmetric_matrix('ChemSep PR', constants.CASs, 'kij')
eos_kwargs = {'Tcs': constants.Tcs, 'Pcs': constants.Pcs, 'omegas': constants.omegas, 'kijs': kijs}

gas = CEOSGas(PRMIX, eos_kwargs, HeatCapacityGases=constants.HeatCapacityGases, T=T, P=P, zs=zs)
liquid = CEOSLiquid(PRMIX, eos_kwargs, HeatCapacityGases=constants.HeatCapacityGases, T=T, P=P, zs=zs)

# Flash calculation
flasher = FlashVL(constants, HeatCapacityGases=constants.HeatCapacityGases, gas=gas, liquids=[liquid])
res = flasher.flash(T=T, P=P, zs=zs)

print(f"Temperature: {T-273.15:.1f} °C")
print(f"Pressure: {P/1e6:.1f} MPa")
print(f"Phase: {res.phase}")
if res.phase == 'L':
    print(f"Liquid density: {res.rho_mass():.1f} kg/m³")
    print(f"Liquid viscosity: {res.mu()*1e6:.2f} μPa·s")

完整工程示例

请参阅 examples.py,其中包含经过验证、可用于生产的示例,包括:

  1. 泵曲线的温度-黏度修正
  2. 温度变化下的 NPSH 计算
  3. 混合燃料的混合物性质计算
  4. 多级泵中的焓升
  5. 泵出口工况的闪蒸计算
  6. 化学数据库查询

泵应用概要

何时使用 Thermo 软件包
  1. 随温度变化的性质:流体温度变化显著时
  2. 混合物处理:泵送混合流体或工艺流体时
  3. 高温应用:锅炉给水泵、导热油泵
  4. 气蚀分析:为 NPSH 计算提供准确的蒸气压
  5. 多相流:确定是否会发生闪蒸
  6. 能量计算:泵温升的热量衡算
与 Fluids 软件包集成

thermo 软件包与 fluids 相辅相成,可进行完整的泵分析:

  • thermo:提供随温度变化的性质(ρ、μ、Psat)
  • fluids:使用这些性质进行水力计算(摩擦、扬程损失)
from thermo.chemical import Chemical
from fluids.core import Reynolds
from fluids.friction import friction_factor

# Get properties from thermo
water = Chemical('water', T=333.15, P=101325)  # 60°C
rho = water.rho
mu = water.mu

# Use in fluids calculations
Re = Reynolds(V=2.0, D=0.1, rho=rho, mu=mu)
f = friction_factor(Re=Re, eD=0.0001)

print(f"At 60°C: Re = {Re:.0f}, f = {f:.5f}")

常见化学品数据库

可通过 CAS 编号或名称访问 20,000 多种化学品:

  • 工业流体(水、油、乙二醇)
  • 烃类(甲烷、丙烷、汽油)
  • 制冷剂(R-134a、氨)
  • 酸和碱(HCl、NaOH)
  • 有机溶剂(乙醇、丙酮)

数据库详情和常见泵送流体请参阅 reference.md。

最佳实践

  1. 创建 Chemical 对象时,始终同时指定 T 和 P
  2. 使用液体属性前,检查相态
  3. 与已知数据进行验证(蒸汽表、RefProp、NIST)
  4. 高压应用(>20 bar)使用合适的 EOS
  5. 考虑关联式的温度范围(有些仅适用于 <150°C)
  6. 缓存 Chemical 对象,以提高迭代计算的性能

单位

所有属性均使用 SI 单位:

  • 温度:K(从 °C 转换:T_K = T_C + 273.15)
  • 压力:Pa(1 bar = 100,000 Pa)
  • 密度:kg/m³
  • 黏度:Pa·s(1 cP = 0.001 Pa·s)
  • 焓:J/kg
  • 热容:J/kg·K

故障排除

问题:属性返回 None
  • 原因:该化学品不提供此属性,或属性值超出有效范围
  • 解决方案:检查 Chemical.Tmin、Chemical.Tmax,确认有效温度范围
问题:混合物属性不合理
  • 原因:缺少相互作用参数或组成无效
  • 解决方案:确认质量分数/摩尔分数之和等于 1.0
问题:闪蒸计算失败
  • 原因:初始猜测超出有效区域,或 EOS 参数有误
  • 解决方案:使用更简单的 EOS(理想气体),或调整初始 T/P 估计值

参考资料

  • DIPPR 801 数据库(AIChE 物性设计研究所)
  • NIST 化学 WebBook
  • Poling, B.E., Prausnitz, J.M., O'Connell, J.P.,《气体与液体的性质》(第 5 版)
  • Perry《化学工程师手册》(第 9 版)
  • Peng, D.Y., Robinson, D.B.,《一种新的双常数状态方程》(1976)

延伸阅读

评论

支持 Markdown