Skip to content

Thermodynamic Properties

PHOENIX provides thermodynamic property estimation using Benson Group Additivity (GA) with reference data comparison.

Overview

Available Properties

Property Symbol Unit Description
Enthalpy of formation ΔHf° kJ/mol Heat of formation from elements
Entropy J/(mol·K) Standard molar entropy
Heat capacity Cp J/(mol·K) Constant pressure heat capacity
Gibbs free energy kJ/mol Calculated as H - TS

Data Sources

  1. Benson Group Additivity - Primary estimation method
  2. Uses pgradd library
  3. Covers most organic functional groups
  4. Typical accuracy: ±5-10 kJ/mol for ΔHf°

  5. Reference Data - For validation and comparison

  6. NIST-JANAF thermochemical tables
  7. chemicals library (CalebBell/ChEDL)

ThermoProperty Class

The ThermoProperty dataclass holds a thermodynamic value with metadata:

from phoenix import Compound

compound = Compound.from_smiles("CCO")
hf = compound.enthalpy_of_formation

# Access value and metadata
print(f"Value: {hf.value} {hf.unit}")
print(f"Source: {hf.source}")
print(f"Uncertainty: {hf.uncertainty}")
print(f"Temperature: {hf.temperature_K} K")

Attributes

Attribute Type Description
value float The property value
unit str Unit of measurement
uncertainty float None
source str None
phase str Phase: 'g', 'l', or 's'
temperature_K float Temperature in Kelvin
breakdown tuple Group contribution details
reference_value ThermoValue None

Using as Float

ThermoProperty can be used directly as a float:

hf = compound.enthalpy_of_formation

# Arithmetic operations
delta_h = float(hf) - 100.0

# Comparisons
if float(hf) < -200:
    print("Highly exothermic formation")

Temperature-Dependent Calculations

Single Temperature

compound = Compound.from_smiles("CCO")

# Default (298.15 K)
hf_default = compound.enthalpy_of_formation
print(f"ΔHf°(298K) = {hf_default.value:.1f} kJ/mol")

# Custom temperature
hf_500 = compound.enthalpy_of_formation(T=500)
print(f"ΔHf°(500K) = {hf_500.value:.1f} kJ/mol")

Multiple Temperatures

Use NumPy arrays for vectorized calculations:

import numpy as np
from phoenix import Compound

compound = Compound.from_smiles("CCO")

# Temperature range
temps = np.linspace(300, 1000, 50)

# Get values at all temperatures
hf_values = compound.enthalpy_of_formation(T=temps)

print(f"Type: {type(hf_values)}")  # numpy.ndarray
print(f"Min: {hf_values.min():.1f}, Max: {hf_values.max():.1f} kJ/mol")

Temperature Warnings

PHOENIX warns for extreme temperatures:

import warnings

compound = Compound.from_smiles("CCO")

# Low temperature warning (<200 K)
hf_low = compound.enthalpy_of_formation(T=100)
# Warning: Temperature 100 K is below 200 K. Benson GA extrapolation may be unreliable.

# High temperature warning (>6000 K)
hf_high = compound.enthalpy_of_formation(T=7000)
# Warning: Temperature 7000 K is above 6000 K. NASA polynomial extrapolation may be unreliable.

ThermoState

Get all properties at a single temperature using thermo_at():

compound = Compound.from_smiles("CCO")

# All properties at 500 K
state = compound.thermo_at(T=500)

print(f"Temperature: {state.temperature} K")
print(f"H  = {state.H.value:>8.1f} kJ/mol")
print(f"S  = {state.S.value:>8.1f} J/(mol·K)")
print(f"Cp = {state.Cp.value:>8.1f} J/(mol·K)")
print(f"G  = {state.G.value:>8.1f} kJ/mol")

State Properties

ThermoState provides both short and long names:

state = compound.thermo_at(T=500)

# Short names
print(state.H.value)   # Enthalpy
print(state.S.value)   # Entropy
print(state.Cp.value)  # Heat capacity
print(state.G.value)   # Gibbs energy

# Long names
print(state.enthalpy.value)
print(state.entropy.value)
print(state.heat_capacity.value)
print(state.gibbs_energy.value)

Gibbs Energy Calculation

Gibbs energy is calculated as:

\[ G = H - T \cdot S \]
state = compound.thermo_at(T=500)

# Verify G calculation
H_kJ = state.H.value
S_kJ_K = state.S.value / 1000  # Convert J to kJ
T = state.temperature

G_calculated = H_kJ - T * S_kJ_K
print(f"G (calculated): {G_calculated:.1f} kJ/mol")
print(f"G (from state): {state.G.value:.1f} kJ/mol")

Group Contribution Breakdown

For Benson GA estimates, view the group breakdown:

compound = Compound.from_smiles("CCC")  # Propane
hf = compound.enthalpy_of_formation

# Check if breakdown is available
if hf.has_breakdown():
    print(hf.format_breakdown())

Output example:

ENTHALPY OF FORMATION (GAS) CALCULATION
============================================================
Group                         Count    Contribution      Total
------------------------------------------------------------
C-(H)3(C)                        2         -10.00       -20.00
C-(H)2(C)2                       1          -5.00        -5.00
------------------------------------------------------------
ESTIMATED VALUE (Benson GA):                           -25.00 kJ/mol

Reference Value Comparison

When reference data is available:

compound = Compound.from_smiles("CCO")
hf = compound.enthalpy_of_formation

# Check for reference value
if hf.has_reference():
    print(f"Estimated: {hf.value:.1f} kJ/mol")
    print(f"Reference: {hf.reference_value.value:.1f} kJ/mol")
    print(f"Deviation: {hf.deviation:.1f} kJ/mol")
    print(f"Deviation: {hf.deviation_percent:.1f}%")

Backward Compatibility

Legacy float properties are still available:

compound = Compound.from_smiles("CCO")

# Legacy properties (at 298.15 K)
hf_kJ = compound.delta_hf_kJ_mol  # float
s_J = compound.entropy_J_mol_K    # float

print(f"ΔHf° = {hf_kJ:.1f} kJ/mol")
print(f"S° = {s_J:.1f} J/(mol·K)")

Benson GA vs Reference Data

When to Trust GA

Benson GA is most accurate for:

  • Simple hydrocarbons
  • Common alcohols, ethers, ketones
  • Well-characterized functional groups

When to Be Cautious

GA may be less accurate for:

  • Strained ring systems
  • Multiple adjacent functional groups
  • Unusual bonding patterns
  • Very large molecules (>100 atoms)

Checking Accuracy

compound = Compound.from_smiles("CCO")
hf = compound.enthalpy_of_formation

# Typical Benson GA uncertainty
typical_uncertainty = 10.0  # kJ/mol

# Check if reference exists for validation
if hf.has_reference():
    actual_deviation = abs(hf.deviation)
    print(f"Deviation from reference: {actual_deviation:.1f} kJ/mol")

    if actual_deviation > 2 * typical_uncertainty:
        print("Warning: Large deviation - validate experimentally")

Temperature Ranges

Valid Ranges

Method Temperature Range
Benson GA 298-1500 K (best)
NASA polynomials 200-6000 K

Extrapolation Warnings

# These will generate warnings
state_cold = compound.thermo_at(T=100)   # Below 200 K
state_hot = compound.thermo_at(T=7000)   # Above 6000 K

Next Steps