Skip to main content

A Python thermodynamic property wrapper for real fluids, ideal gases, and liquid rocket propellants.

Project description

ThermoProp

PyPI version Python License

ThermoProp is a Python thermodynamic property wrapper for real fluids, mixtures, ideal gases, and liquid rocket propellants.

It provides a clean interface around:

  • CoolProp
  • PYroMat
  • RocketProps
  • NumPy
  • SciPy

Why ThermoProp?

ThermoProp provides a unified API around CoolProp, PYroMat, and RocketProps.

Instead of remembering backend-specific syntax such as:

CP.PropsSI(...)
pm.get(...)
get_prop(...)

users can write:

from thermoprop import Fluid

water = Fluid(
    "water",
    pressure=101325,
    temperature=300,
)

print(water.density)
print(water.enthalpy)

with a consistent interface for pure fluids, mixtures, ideal gases, and liquid rocket propellants.

Installation

pip install thermoprop

Features

Fluid

Fluid is a CoolProp-based real-fluid wrapper.

It supports:

  • Pure fluids
  • Fluid mixtures
  • Pressure-temperature states
  • Pressure-enthalpy states
  • Pressure-quality states
  • Temperature-quality states
  • Density-based states
  • Mass-fraction and mole-fraction mixtures

IdealGas

IdealGas is a PYroMat-based ideal-gas wrapper.

It supports:

  • Pure ideal gases
  • Ideal-gas mixtures
  • Temperature states
  • Enthalpy states
  • Internal-energy states
  • Pressure-density closure
  • Cp, Cv, gamma, entropy, Gibbs energy, and speed of sound

Propellant

Propellant is a RocketProps-based liquid rocket propellant wrapper.

It supports:

  • Liquid rocket propellants
  • Saturated-liquid properties
  • Compressed-liquid properties
  • Density
  • Dynamic viscosity
  • Kinematic viscosity
  • Thermal conductivity
  • Surface tension
  • Vapor pressure
  • Saturation temperature
  • Heat of vaporization
  • Critical properties

Propellant is intended for liquid propellant engineering properties. It is not a thermodynamic flash solver and does not calculate vapor-state properties, two-phase states, enthalpy, internal energy, or entropy.

FluidRegistry

FluidRegistry maps user-friendly names and aliases to backend-specific names.

For example:

from thermoprop import FluidRegistry

print(FluidRegistry.coolprop_name("rp-1"))
print(FluidRegistry.propellant_name("rp-1"))

outputs different backend names:

n-Dodecane
RP1

This is intentional. Fluid("rp-1") uses CoolProp's n-Dodecane as an RP-1 surrogate, while Propellant("rp-1") uses RocketProps' actual RP1 correlation.

Thermodynamic Reference States

ThermoProp provides a unified interface to multiple thermodynamic backends.

Different property libraries may use different reference states for properties such as:

  • Enthalpy
  • Internal energy
  • Entropy

As a result, absolute values of these properties may differ between ThermoProp classes even when pressure, temperature, and composition are identical.

For example, two wrappers representing the same physical state may report different absolute enthalpy values if their underlying thermodynamic libraries use different energy reference conventions.

This behavior is expected and does not indicate an error.

Most engineering calculations depend on property differences rather than absolute values. Properties such as:

  • Temperature
  • Pressure
  • Density
  • Specific heats
  • Speed of sound
  • Enthalpy differences (Δh)
  • Internal-energy differences (Δu)

remain physically meaningful within each backend.

Users combining results from multiple ThermoProp wrappers should establish a consistent thermodynamic reference basis if absolute values of enthalpy, internal energy, or entropy are required.

Pure Fluid Example

from thermoprop import Fluid

water = Fluid(
    "water",
    pressure=101325,
    temperature=300,
)

print(water.density)
print(water.enthalpy)
print(water.phase)

Pressure-Enthalpy Example

from thermoprop import Fluid

water = Fluid(
    "water",
    pressure=101325,
    enthalpy=2.7e6,
)

print(water.temperature)
print(water.quality)
print(water.phase)

Mixture Example

from thermoprop import Fluid

air_like = Fluid(
    {"nitrogen": 0.79, "oxygen": 0.21},
    basis="mole",
    pressure=101325,
    temperature=300,
)

print(air_like.density)
print(air_like.specific_heat_cp)

Ideal Gas Example

from thermoprop import IdealGas

nitrogen = IdealGas(
    "gn2",
    pressure=101325,
    temperature=300,
)

print(nitrogen.density)
print(nitrogen.specific_heat_ratio)
print(nitrogen.speed_of_sound)

Propellant Example

from thermoprop import Propellant

rp1 = Propellant(
    "rp1",
    temperature=293.15,
)

print(rp1.density)
print(rp1.dynamic_viscosity)
print(rp1.vapor_pressure)

Compressed-Liquid Propellant Example

from thermoprop import Propellant

lox = Propellant(
    "lox",
    pressure=3e6,
    temperature=90,
)

print(lox.density)
print(lox.dynamic_viscosity)
print(lox.saturation_pressure)

Propellant Cavitation Margin Example

from thermoprop import Propellant

lox = Propellant(
    "lox",
    pressure=300000,
    temperature=90,
)

margin = lox.pressure - lox.vapor_pressure

print(margin)

Fluid Registry Examples

FluidRegistry can be used to inspect supported names, check backend support, and add custom aliases.

Check Backend Names

from thermoprop import FluidRegistry

print(FluidRegistry.coolprop_name("water"))
print(FluidRegistry.pyromat_name("gn2"))
print(FluidRegistry.propellant_name("rp-1"))

Example output:

Water
N2
RP1

For PYroMat, the ig. prefix can also be requested:

print(FluidRegistry.pyromat_name("gn2", include_prefix=True))

Example output:

ig.N2

Check Backend Support

from thermoprop import FluidRegistry

print(FluidRegistry.supports_coolprop("water"))
print(FluidRegistry.supports_pyromat("gn2"))
print(FluidRegistry.supports_propellant("rp-1"))

List Supported Names

from thermoprop import FluidRegistry

print(FluidRegistry.names)
print(FluidRegistry.coolprop_supported_names)
print(FluidRegistry.pyromat_supported_names)
print(FluidRegistry.propellant_supported_names)

You can also print supported species directly:

FluidRegistry.show_species()
FluidRegistry.show_coolprop_species()
FluidRegistry.show_pyromat_species()
FluidRegistry.show_propellant_species()

Show Aliases

ThermoProp keeps normal fluid aliases and propellant aliases separate.

from thermoprop import FluidRegistry

FluidRegistry.show_aliases()
FluidRegistry.show_propellant_aliases()

This avoids ambiguity. For example:

print(FluidRegistry.coolprop_name("rp-1"))
print(FluidRegistry.propellant_name("rp-1"))

returns:

n-Dodecane
RP1

Add Custom Aliases

Use add_alias() for Fluid and IdealGas names:

from thermoprop import Fluid, FluidRegistry

FluidRegistry.add_alias("my-water", "Water")

water = Fluid(
    "my-water",
    pressure=101325,
    temperature=300,
)

print(water.density)

Use add_propellant_alias() for Propellant names:

from thermoprop import Propellant, FluidRegistry

FluidRegistry.add_propellant_alias("my-rp1", "RP1")

rp1 = Propellant(
    "my-rp1",
    temperature=293.15,
)

print(rp1.density)

Removing aliases works the same way:

FluidRegistry.remove_alias("my-water")
FluidRegistry.remove_propellant_alias("my-rp1")

Common Properties

from thermoprop import Fluid

fluid = Fluid(
    "water",
    pressure=101325,
    temperature=300,
)

print(fluid.pressure)
print(fluid.temperature)
print(fluid.density)
print(fluid.enthalpy)
print(fluid.entropy)
print(fluid.specific_heat_cp)
print(fluid.specific_heat_cv)
print(fluid.specific_heat_ratio)
print(fluid.speed_of_sound)
print(fluid.dynamic_viscosity)
print(fluid.conductivity)

Updating State Properties

ThermoProp states can be updated after creation.

Real Fluid

from thermoprop import Fluid

water = Fluid(
    "water",
    pressure=101325,
    temperature=300,
)

water.pressure = 2e5
water.temperature = 350

print(water.density)
print(water.enthalpy)

You can also update state pairs directly:

water.pressure_temperature = (2e5, 350)
water.pressure_enthalpy = (2e5, 1.5e6)
water.pressure_quality = (101325, 0.5)
water.temperature_quality = (373.15, 1.0)

Ideal Gas

Ideal gases only require a thermal state such as temperature, enthalpy, or internal energy.

from thermoprop import IdealGas

nitrogen = IdealGas(
    "gn2",
    temperature=300,
)

print(nitrogen.enthalpy)
print(nitrogen.internal_energy)
print(nitrogen.specific_heat_cp)

Pressure is optional, but it is required for pressure-dependent properties such as density and entropy:

nitrogen.pressure = 101325

print(nitrogen.density)
print(nitrogen.entropy)

You can also update ideal-gas states:

nitrogen.temperature = 500
nitrogen.pressure_temperature = (101325, 300)
nitrogen.pressure_enthalpy = (101325, nitrogen.enthalpy)

Propellant

Propellants require temperature. Pressure is optional.

from thermoprop import Propellant

rp1 = Propellant(
    "rp1",
    temperature=293.15,
)

print(rp1.density)
print(rp1.specific_heat_cp)

If pressure is omitted, saturated-liquid properties are used.

rp1.pressure = 2e6

print(rp1.density)
print(rp1.dynamic_viscosity)

You can also update the propellant state pair directly:

rp1.pressure_temperature = (2e6, 300)

Propellant Limitations

Propellant wraps RocketProps liquid propellant correlations.

It is intended for liquid engineering properties and does not calculate:

  • Vapor-state properties
  • Two-phase flash states
  • Enthalpy
  • Internal energy
  • Entropy
  • Cv
  • Specific heat ratio
  • Speed of sound

Unsupported properties raise NotImplementedError.

Ideal-Gas Viscosity Limitation

IdealGas.dynamic_viscosity uses Sutherland's law.

Currently, viscosity is only supported for selected pure gases, including:

  • Air
  • Argon
  • Carbon dioxide
  • Carbon monoxide
  • Nitrogen
  • Oxygen
  • Hydrogen
  • Water vapor

Mixture viscosity is not currently supported.

from thermoprop import IdealGas

air = IdealGas(
    "air",
    pressure=101325,
    temperature=300,
)

print(air.dynamic_viscosity)

If viscosity data is unavailable for a gas, ThermoProp raises NotImplementedError.

Source Code

GitHub:

https://github.com/saakethramoju/ThermoProp

License

ThermoProp is released under the GNU General Public License v3.0.

See LICENSE and THIRD_PARTY_LICENSES.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

thermoprop-0.2.1.tar.gz (26.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

thermoprop-0.2.1-py3-none-any.whl (28.5 kB view details)

Uploaded Python 3

File details

Details for the file thermoprop-0.2.1.tar.gz.

File metadata

  • Download URL: thermoprop-0.2.1.tar.gz
  • Upload date:
  • Size: 26.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for thermoprop-0.2.1.tar.gz
Algorithm Hash digest
SHA256 d0dd8b77eb01dc5b66d7a4487d51adb0b3c9af09ee5f62a62a2a9d591dbae64c
MD5 1ccd58b720fb8cc3a6882a7227186776
BLAKE2b-256 829efb8470912686e2347b8f7b6356dc18029e7209c4c33e783f9072df7a2dca

See more details on using hashes here.

File details

Details for the file thermoprop-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: thermoprop-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 28.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for thermoprop-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ac19b6e36ac0a1cf7c8825539d4f9b089424db4b1113c02a05bf6f7b720f1603
MD5 e77349d600076fcfadeeccb3d6427ae8
BLAKE2b-256 31f827d0f81b619ec9f55c98ac21c5484e3c7263e9c3859082fe66a4922db6b0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page