mcpField
C
chempy

chempy

github.com/tondevrel其他2476 次安装38 周前更新
代码仓库

关于 chempy

ChemPy 是用于化学计算的 Python 库,面向研究人员及化学反应和物理化学建模开发者。它将化学符号转化为配平反应、动力学常微分方程系统和化学平衡计算。

主要功能

  1. 01配平化学计量及氧化还原反应
  2. 02用常微分方程模拟动力学
  3. 03计算平衡与物种分布
  4. 04处理单位、离子强度和活度
  5. 05解析化学式并计算摩尔质量
  6. 06将反应输出为 LaTeX 或 HTML

适用场景

  1. 01配平离子反应或氧化还原方程
  2. 02模拟浓度随时间的变化
  3. 03估算缓冲液 pH 和化学形态分布
  4. 04计算电解质溶液的活度系数

安装

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

$npx skills add https://github.com/tondevrel/scientific-agent-skills --skill chempy

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

详细介绍

ChemPy - 物理化学与分析化学

ChemPy 提供了系统化的方式来处理化学实体和反应。它可以自动配平复杂的氧化还原反应,求解动力学常微分方程(ODE)组,并计算平衡体系中的物种分布。

适用场景

  • 配平化学方程式(包括离子反应和氧化还原反应)。
  • 使用 ODE 求解器模拟化学动力学(浓度随时间的变化)。
  • 计算化学平衡和物种分布(例如缓冲溶液的 pH)。
  • 在化学计算中处理物理常数和单位。
  • 建模离子强度和活度系数(Debye-Hückel)。
  • 解析化学式并计算摩尔质量。
  • 生成化学反应的 LaTeX 或 HTML 表示形式。

参考文档

官方文档:https://bjodah.github.io/chempy/
GitHub:https://github.com/bjodah/chempy
搜索模式:chempy.Reaction、chempy.ReactionSystem、chempy.balance_stoichiometry、chempy.kinetics

核心原则

化学实体

表示为字符串('H2O'、'Fe+3')或 Substance 对象。ChemPy 可以解析这些内容,以确定组成和电荷。

反应系统

由一组 Reaction 对象组成。此系统可以转换为数学模型(ODE),其中速率由质量作用动力学或自定义速率定律定义。

单位

ChemPy 集成了 quantities 或 pint,以确保量纲正确,这对于计算速率(例如 M⁻¹s⁻¹)至关重要。

快速参考

安装
pip install chempy
标准导入
import numpy as np
import matplotlib.pyplot as plt
from chempy import Reaction, ReactionSystem, Substance
from chempy.util.parsing import formula_to_composition
基本模式 - 配平反应
from chempy import balance_stoichiometry

# 1. Define reactants and products
reac, prod = balance_stoichiometry({'H2', 'O2'}, {'H2O'})

# 2. Output coefficients
print(reac) # {'H2': 2, 'O2': 1}
print(prod) # {'H2O': 2}

关键规则

✅ 应该做
  • 使用标准记法 - 遵循标准化学记法书写化学式('H2SO4'、'Fe+3'),以确保可靠解析。
  • 定义 ReactionSystem - 对于任何复杂网络,都应将反应封装在 ReactionSystem 中,以便统一管理物质和速率。
  • 检查质量/电荷平衡 - 在运行动力学模拟前,务必确认反应已配平。
  • 使用单位 - 尽可能使用单位库,避免时间尺度或浓度单位出错。
  • 指定速率定律 - 明确说明反应是基元反应(质量作用)还是遵循自定义速率定律。
  • 向量化浓度 - 向求解器提供初始浓度时使用 NumPy 数组。
❌ 不要做
  • 手动配平复杂方程式 - 交由 balance_stoichiometry 处理,尤其是氧化还原反应。
  • 忽略离子强度 - 在分析化学中,请记住活度系数会随离子强度变化(使用 chempy.einstein)。
  • 假设平衡快速完成 - 在动力学模型中,确保“瞬时”步骤的速率常数足够大,但又不会导致数值刚性。
  • 硬编码摩尔质量 - 使用 Substance.from_formula('H2O').mass 以确保精度。

反模式(绝对不要)

from chempy import balance_stoichiometry

# ❌ BAD: Manual string parsing to find mass
# mass = 1.008 * 2 + 16.00 # Fragile and tedious

# ✅ GOOD: Use Substance properties
from chempy import Substance
water = Substance.from_formula('H2O')
print(water.mass)

# ❌ BAD: Hardcoding ODEs for kinetics
# def dc_dt(c, t): return [-k*c[0]*c[1], ...] # Error-prone

# ✅ GOOD: Generate ODE from ReactionSystem
from chempy.kinetics.ode import get_odesys
rsys = ReactionSystem.from_string("A + B -> C; k")
odesys, extra = get_odesys(rsys)
# This handles all derivatives automatically

化学计量与化学式

高级配平(氧化还原)
from chempy import balance_stoichiometry

# Balancing KMn04 + HCl reaction
reactants = {'KMnO4', 'HCl'}
products = {'KCl', 'MnCl2', 'H2O', 'Cl2'}
reac, prod = balance_stoichiometry(reactants, products)

print(f"Balanced: 2 KMnO4 + 16 HCl -> 2 KCl + 2 MnCl2 + 8 H2O + 5 Cl2")
Substance 属性
from chempy import Substance

# Create substance with metadata
ferric = Substance('Fe+3', name='Iron(III) ion', latex='Fe^{3+}')
print(ferric.composition) # {26: 1} - Atomic number 26
print(ferric.charge)      # 3

化学动力学(chempy.kinetics)

模拟浓度随时间的变化
from chempy import ReactionSystem
from chempy.kinetics.ode import get_odesys
import numpy as np

# 1. Define the system: 2A -> B (rate constant k=0.5)
rsys = ReactionSystem.from_string("2 A -> B; 0.5")

# 2. Get the ODE system
odesys, extra = get_odesys(rsys)

# 3. Integrate
tout = np.linspace(0, 10, 50)
c0 = {'A': 1.0, 'B': 0.0}
result = odesys.integrate(tout, c0)

# 4. Plot
plt.plot(result.tout, result.cout)
plt.legend(rsys.substances.keys())

化学平衡

计算物种分布
from chempy.equilibria import EqSystem

# Define equilibria: H2O <-> H+ + OH- (Kw = 1e-14)
# and acetic acid dissociation
eqsys = EqSystem.from_string("""
H2O <-> H+ + OH-; 1e-14
CH3COOH <-> CH3COO- + H+; 1.75e-5
""")

# Calculate concentrations given initial state
init_conc = {'H2O': 55.5, 'CH3COOH': 0.1, 'H+': 1e-7, 'OH-': 1e-7, 'CH3COO-': 0}
final_conc, info = eqsys.root(init_conc)

print(f"pH: {-np.log10(final_conc[eqsys.substances.index('H+')]):.2f}")

物理化学工具

离子强度与活度
from chempy.electrolytes import ion_strength, davies_activity_coefficient

# Calculate ionic strength of 0.1M Na2SO4
molalities = {'Na+': 0.2, 'SO4-2': 0.1}
I = ion_strength(molalities)

# Davies activity coefficient (extension of Debye-Hückel)
gamma = davies_activity_coefficient(I, z=2, eps=78.3, T=298.15)
print(f"Activity coefficient for SO4-2: {gamma:.3f}")

实用工作流

1. 滴定曲线模拟
def simulate_titration(acid_conc, base_concs):
    """Calculates pH as base is added to an acid."""
    results = []
    for cb in base_concs:
        # Define complex equilibrium system for each step
        eqsys = EqSystem.from_string(f"HA <-> H+ + A-; 1e-5\nH2O <-> H+ + OH-; 1e-14")
        # Solve for H+ concentration
        ...
    return results
2. 酶动力学(Michaelis-Menten ODE)
def enzyme_kinetics():
    # E + S <-> ES -> E + P
    rsys = ReactionSystem.from_string("""
    E + S <-> ES; 1e6, 1e2
    ES -> E + P; 1e3
    """)
    odesys, _ = get_odesys(rsys)
    # Integrate to see substrate depletion and product formation
    ...
3. 大气化学模型
def ozone_cycle():
    # Simple Chapman Cycle
    reactions = """
    O2 -> 2 O; k1
    O + O2 -> O3; k2
    O3 -> O + O2; k3
    O + O3 -> 2 O2; k4
    """
    rsys = ReactionSystem.from_string(reactions)
    # Solve for steady-state ozone concentration
    ...

性能优化

符号推导

ChemPy 在底层使用 SymPy 推导 ODE 系统的雅可比矩阵。这使积分速度显著快于数值估算雅可比矩阵,也更加稳定。

原生代码生成

对于非常大的系统,ChemPy 可以使用 pyodesys 将化学反应网络生成 C++ 或 Fortran 代码,随后编译并从 Python 调用。

常见问题与解决方案

“刚性系统”问题

化学系统中的反应往往具有差异很大的时间尺度(快速质子转移与缓慢燃烧)。

# ✅ Solution: Use a stiff-capable solver (like 'cvode' or 'lsoda')
result = odesys.integrate(tout, c0, integrator='lsoda')
化学式解析的歧义

“Co”可能表示钴,也可能表示碳 + 氧。

# ❌ Problem: formula_to_composition('Co') -> {27: 1} (Cobalt)
# ✅ Solution: Use Substance objects to be explicit
sub = Substance('CO', name='Carbon Monoxide')
单位与浮点数

平衡常数(K)的取值范围可能跨越 50 个数量级(10⁻⁵⁰ 到 10²⁰)。

# ❌ Problem: Standard root finders might fail on small values
# ✅ Solution: Solve in log-space (log-concentrations)
final_conc, info = eqsys.root(init_conc, use_log=True)

ChemPy 将物理化学的精确性带入 Python 世界。通过自动完成从化学符号到数学模型的转换,它让研究人员能够专注于化学本身,而非底层微分方程。

评论

支持 Markdown