ChemPy

repository·master·Indexed 20 days ago

https://github.com/bjodah/chempy

A Python library for physical, inorganic, and analytical chemistry. It provides tools for chemical kinetics (including mass action and Eyring transition state theory), equilibrium solving with various numerical transformations (NumSys), and physical chemistry property calculations. Key features include reaction system simulation with temperature ramps, stoichiometry balancing, unit-aware dictionaries via QuantityDict, and a Solution class for modeling chemical solutions.

Tokens
49.4K
Snippets
173
Records
188
Agent score
71%

What's inside chempy

  1. Overview of ChemPy capabilities

    master

    ChemPy is a Python library designed for researchers and engineers to solve chemistry-related problems through modeling. It provides core abstractions for representing substances, reactions, and reaction systems, and supports both numerical and symbolic computation.

    Key Capabilities:

    • Chemical Representation: Classes for substances (with composition, weight, charge, and pretty-printing via LaTeX/HTML/Unicode) and reactions (defined by stoichiometry and thermodynamic/kinetic parameters).
    • Reaction Systems: Tools to analyze reaction networks (e.g., identifying disjoint sets or connectivity) and express them as:
      • Systems of Ordinary Differential Equations (ODEs) for chemical kinetics.
      • Systems of non-linear equations for chemical equilibria (including multi-phase systems).
    • Mathematical Solving:
      • Symbolic Math: Uses SymPy to solve stoichiometry problems analytically, including under-determined systems.
      • Numerical Solving: Integrates with pyodesys for ODEs and pyneqsys for non-linear equations.
      • Optimization: Uses PuLP to express under-determined systems in a canonical form with minimized coefficients.
    • Data Support: Supports NumPy arrays, symbolic inputs, and arrays with explicit units for dimensionality checking (e.g., verifying reaction order against rate constants).
  2. Overview of ChemPy capabilities

    master

    ChemPy is a Python package designed for physical, inorganic, and analytical chemistry. Its core features include:

    • Chemical Kinetics: Numerical integration routines for ODE solvers and integrated rate expressions (including fitting routines).
    • Equilibria: Solvers for chemical equilibria, including multiphase systems.
    • Physical Chemistry Relations: Implementations of Debye-Hückel, Arrhenius & Eyring, and Einstein-Smoluchowski equations.
    • Chemical Properties: Pure Python implementations of literature-based properties, such as:
      • Water density (as a function of temperature)
      • Water permittivity (as a function of temperature and pressure)
      • Water diffusivity (as a function of temperature)
      • Water viscosity (as a function of temperature)
      • Sulfuric acid density (as a function of temperature and weight fraction H₂SO₄)
  3. Manipulate chemical equilibria and redox reactions

    master

    ChemPy provides Equilibrium objects to represent chemical equilibria and perform algebraic manipulations like eliminating species or combining reactions.

    • Eliminate species: Use Equilibrium.eliminate([eq1, eq2, ...], 'species_name') to find coefficients that cancel out a specific species.
    • Combine reactions: Multiply an Equilibrium object by a coefficient and add it to another to create a new combined reaction.
    • Cancel species: Use redox.cancel(autoprot) to find a multiplier that allows adding an autoprotolysis reaction (like water) to a redox reaction to simplify the system.
    from chempy import Equilibrium
    from sympy import symbols
    
    K1, K2 = symbols('K1 K2')
    e1 = Equilibrium({'MnO4-': 1, 'H+': 8, 'e-': 5}, {'Mn+2': 1, 'H2O': 4}, K1)
    e2 = Equilibrium({'O2': 1, 'H2O': 2, 'e-': 4}, {'OH-': 4}, K2)
    
    # Eliminate 'e-' to combine reactions
    coeff = Equilibrium.eliminate([e1, e2], 'e-')
    redox = e1*coeff[0] + e2*coeff[1]
  4. Core abstractions in ChemPy

    master

    ChemPy is built around several hierarchical abstractions that allow you to model chemical environments:

    1. Substances: The fundamental building blocks. They hold names, composition, weight, and charge. ChemPy can parse chemical formulae to deduce these properties and provides stylistic representations for LaTeX, HTML, and Unicode.
    2. Reactions: Defined by their stoichiometry and kinetic/thermodynamic parameters. If stoichiometry is unknown, ChemPy can automatically balance reactions based on substance composition.
    3. Reaction Systems: Higher-level containers that manage collections of reactions. They include validation checks at initialization to ensure reactions are balanced, coefficients are sane, and units are consistent. They can be analyzed as graphs or tables and converted into mathematical systems (ODEs or non-linear equations).
  5. Install ChemPy via pip

    master

    On Windows and macOS, use pip to install ChemPy.

    For a standard installation:

    $ python3 -m pip install chempy pytest
    $ python3 -m pytest -rs -W ignore::chempy.ChemPyDeprecationWarning --pyargs chempy

    For a user-level installation (if you do not have root permissions):

    $ python3 -m pip install --user --upgrade chempy pytest
    $ python3 -m pytest -rs --pyargs chempy

    Note: Some tests may be skipped if optional backends (like those in SciPy) are missing.

  6. Run ChemPy in a Docker environment

    master

    If you have Docker installed, you can use the provided scripts to host a Jupyter notebook server or run the test suite in a controlled environment.

    To host a Jupyter notebook server:

    $ ./scripts/host-env.sh host-notebook --port 8888

    To run the test suite using the Docker image:

    $ ./scripts/host-env.sh run-tests
  7. Install ChemPy with all optional backends

    master

    To enable advanced solvers for ODE systems and non-linear optimization problems (beyond the default SciPy backends), install ChemPy with the [all] extra. This will attempt to install several specialized libraries:

    • pygslodeiv2: Requires GSL (>=1.16).
    • pyodeint: Requires boost (>=1.65.0).
    • pycvodes: Requires SUNDIALS (>=5.3.0).
    • pykinsol: Requires SUNDIALS (>=5.3.0).
    • pycompilation: Requires gcc/clang/icpc.
    • pycodeexport: Used for C++ code generation.
    $ python3 -m pip install chempy[all]
  8. Install ChemPy via Conda

    master

    The simplest way to install ChemPy and its optional dependencies on Linux is using the conda package manager from the conda-forge channel. It is recommended to install pytest alongside it to verify the installation.

    To install and run tests:

    $ conda install -c conda-forge chempy pytest
    $ pytest -rs -W ignore::chempy.ChemPyDeprecationWarning --pyargs chempy
  9. Model chemical kinetics using ODE systems

    master

    To investigate the time dependence of a chemical system (chemical kinetics), use ReactionSystem and get_odesys from chempy.kinetics.ode.

    1. Define a ReactionSystem using from_string() with reaction formulas and rate constants.
    2. Convert the system to an ODE system using get_odesys(rsys).
    3. Integrate the system over a time array using odesys.integrate(tout, c0, ...), where c0 is the initial concentration dictionary.
    4. Use the returned result object to plot concentrations over time.
    from chempy import ReactionSystem
    from chempy.kinetics.ode import get_odesys
    import numpy as np
    
    rsys = ReactionSystem.from_string("""2 Fe+2 + H2O2 -> 2 Fe+3 + 2 OH-; 42
        2 Fe+3 + H2O2 -> 2 Fe+2 + O2 + 2 H+; 17
        H+ + OH- -> H2O; 1e10
        H2O -> H+ + OH-; 1e-4""")
    
    odesys, extra = get_odesys(rsys)
    tout = np.linspace(0, 23, 100)
    c0 = {'Fe+2': 0.05, 'H2O2': 0.1, 'H2O': 1.0, 'H+': 1e-2, 'OH-': 1e-12}
    
    result = odesys.integrate(tout, c0)
    result.plot()
  10. Improve convergence using NumSysLog

    master

    Non-linear chemical systems can be difficult to solve due to concentration scales spanning many orders of magnitude. You can pass a NumSys (Numerical System) transformation to the .root() method to improve convergence. NumSysLog solves for the logarithm of the concentrations, which is often more stable.

    from chempy.equilibria import EqSystem, NumSysLog
    
    # Standard solve
    x, sol, sane = eqsys.root(init_conc)
    
    # Solve using log-transformed system for better stability
    logx, logsol, sane = eqsys.root(init_conc, NumSys=(NumSysLog,))
  11. How NumSys classes transform equilibrium systems for solvers

    master

    The NumSys hierarchy (and its subclasses like NumSysLin, NumSysLog, NumSysSquare, NumSysLinTanh) provides a way to transform the equilibrium equations into a form more suitable for numerical solvers. This is achieved through a transformation pipeline:

    1. Pre-processing: Transforms the solver's input variables (e.g., from log-space back to concentration space).
    2. Function f(yvec, params): Defines the residual function (the equations that should equal zero) in the transformed space.
    3. Post-processing: Transforms the solver's output back into physical concentrations.

    Common Transformation Strategies

    • NumSysLog: Solves in log-space ($\ln(C)$). This is highly effective for handling concentrations spanning many orders of magnitude and naturally enforces positivity.
    • NumSysSquare: Solves for the square of the concentration ($C^2$), which can help with certain algebraic structures.
    • NumSysLin: Standard linear transformation approach.
    • NumSysLinTanh: Uses a hyperbolic tangent transformation to map the solver's domain to a bounded concentration range $[0, y_{max}]$.
  12. Improve numerical stability with ScaledSys or Log-space integration

    master

    For systems with widely varying concentration scales (stiff problems), you can improve stability using two main approaches:

    1. Scaling: Use pyodesys.symbolic.ScaledSys via get_odesys to scale dependencies.
    2. Log-space integration: Solve for the logarithm of concentrations to avoid negative values. This is done by creating a custom SymbolicSys using pyodesys.symbolic.symmetricsys with sympy.log and sympy.exp.

    Note: Log-space integration can significantly increase the number of function evaluations (computational overhead).

    # Log-space integration setup
    from pyodesys.symbolic import symmetricsys
    import sympy
    
    logexp = (sympy.log, sympy.exp)
    LogLogSys = symmetricsys(logexp, logexp, exprs_process_cb=lambda exprs: [sympy.powsimp(expr.expand(), force=True) for expr in exprs])
    loglogsys, _ = get_odesys(rsys, SymbolicSys=LogLogSys)
    
    # Integrate using the log-space system
    result = loglogsys.integrate(tout, c0, integrator='gsl')