eos¶
Status: active in the ./mk mesa build.
Purpose: call MESA eos for known density, temperature, and static
composition, including scalar calls, profile calls, and inverse density or
temperature solves.
Fast start¶
import numpy as np
from pyfortmesa import mesa
mesa.set_inlist("inlist_eos_and_kap")
mix = mesa.composition({"h1": 0.70, "he4": 0.28, "c12": 0.02})
eos = mesa.Eos()
T = 1.0e7
rho = 1.0e2
small = eos.dt(T=T, Rho=rho, comp=mix)
full = eos.dt_full(T=T, Rho=rho, comp=mix)
Pgas = np.exp(full["results"]["lnPgas"])
Prad = mesa.constants()["crad"] * T**4 / 3.0
Ptot = Pgas + Prad
Pressure and energy conventions¶
MESA's eos result vector stores gas pressure:
results["lnPgas"] = ln(Pgas)
Pgas = total pressure - radiation pressure
Radiation pressure is not a separate eos result. Reconstruct it from temperature:
Pgas = np.exp(out["results"]["lnPgas"])
Prad = mesa.constants()["crad"] * T**4 / 3.0
Ptot = Pgas + Prad
For energy:
Etotal = np.exp(out["results"]["lnE"])
Erad = mesa.constants()["crad"] * T**4 / Rho
Egas = Etotal - Erad
So lnPgas is gas-only, while other thermodynamic quantities such as lnE,
lnS, Cp, grad_ad, chiRho, chiT, and gamma1 are MESA eos
thermodynamic results and should not be treated as a gas-only namespace.
Public API¶
mesa.eos_dt(...) and mesa.Eos().dt(...)¶
Signature:
mesa.eos_dt(
T: float,
Rho: float,
comp: Composition | Mapping[str, float] | Iterable[float] | None = None,
) -> dict[str, float]
Inputs:
| argument | units | shape | meaning |
|---|---|---|---|
T |
K | scalar | temperature |
Rho |
g cm^-3 |
scalar | density |
comp |
mass fraction | scalar composition | Composition, isotope mapping, legacy vector, or None |
Returns the small teaching output:
| key | units | meaning |
|---|---|---|
lnPgas |
ln(dyn cm^-2) |
natural log gas pressure |
lnE |
ln(erg g^-1) |
natural log specific internal energy |
lnS |
ln(erg g^-1 K^-1) |
natural log specific entropy |
grad_ad |
dimensionless | dlnT/dlnP at constant entropy |
gamma1 |
dimensionless | dlnP/dlnRho at constant entropy |
Example:
small = mesa.Eos().dt(T=1.0e7, Rho=1.0e2, comp=mix)
print(small["gamma1"])
mesa.eos_dt_raw(...) and mesa.Eos().dt_raw(...)¶
Signature:
mesa.eos_dt_raw(
T: float,
Rho: float,
chem_id_values: Iterable[int],
xa: Iterable[float],
*,
validate: bool = False,
) -> tuple[float, float, float, float, float]
This is the scalar fast path for a caller that has already prepared the
composition. It skips Composition validation and dictionary construction.
Returns:
lnPgas, lnE, lnS, grad_ad, gamma1
Example:
eos = mesa.Eos()
eos.dt_raw(T=1.0e7, Rho=1.0e2, chem_id_values=mix.chem_id, xa=mix.xa)
for T, rho in scalar_points:
lnPgas, lnE, lnS, grad_ad, gamma1 = eos.dt_raw(T, rho, mix.chem_id, mix.xa)
Use validate=True when accepting untrusted arrays. Keep it False for hot
loops where chem_id_values and xa were prepared once by mesa.composition.
mesa.eos_dt_full(...) and mesa.Eos().dt_full(...)¶
Signature:
mesa.eos_dt_full(
T: float,
Rho: float,
comp: Composition | Mapping[str, float] | Iterable[float] | None = None,
) -> dict[str, dict[str, float] | dict[str, dict[str, float]]]
Inputs are the same as eos_dt(...).
Returns:
| key | shape | meaning |
|---|---|---|
results |
dict by eos result name | full MESA eosDT_get result vector |
d_dlnRho |
dict by eos result name | derivative at constant T |
d_dlnT |
dict by eos result name | derivative at constant Rho |
d_dxa |
nested dict | composition derivatives for lnPgas and lnE |
Representative result names:
lnPgas, lnE, lnS, mu, lnfree_e, eta, grad_ad, chiRho, chiT,
Cp, Cv, dE_dRho, dS_dT, dS_dRho, gamma1, gamma3, phase,
latent_ddlnT, latent_ddlnRho,
HELM, OPAL/SCVH, FreeEOS, PC, Skye, CMS, ideal
Example:
full = mesa.Eos().dt_full(T=1.0e7, Rho=1.0e2, comp=mix)
print(full["results"]["lnPgas"])
print(full["d_dlnT"]["lnPgas"])
print(full["d_dxa"]["lnPgas"]["h1"])
mesa.eos_dt_full_raw(...) and mesa.Eos().dt_full_raw(...)¶
Signature:
mesa.eos_dt_full_raw(
T: float,
Rho: float,
chem_id_values: Iterable[int],
xa: Iterable[float],
*,
validate: bool = False,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]
Returns raw arrays:
results, d_dlnRho, d_dlnT, d_dxa
results, d_dlnRho, and d_dlnT use mesa.EOS_RESULT_NAMES as row names.
d_dxa has shape (2, species) and uses lnPgas, lnE order for the first
axis.
Example:
results, d_dlnRho, d_dlnT, d_dxa = mesa.Eos().dt_full_raw(
1.0e7, 1.0e2, mix.chem_id, mix.xa
)
i_gamma1 = mesa.EOS_RESULT_NAMES.index("gamma1")
gamma1 = results[i_gamma1]
mesa.eos_dt_profile(...) and mesa.Eos().dt_profile(...)¶
Signature:
mesa.eos_dt_profile(
T: Iterable[float],
Rho: Iterable[float],
chem_id_values: Iterable[int],
xa: object,
*,
input_mode: str = "value",
output: str = "raw",
) -> dict[str, object]
Inputs:
| argument | units | shape | meaning |
|---|---|---|---|
T |
K | (nzones,) |
temperature profile |
Rho |
g cm^-3 |
(nzones,) |
density profile |
chem_id_values |
MESA id | (species,) |
isotope ids in xa row order |
xa |
mass fraction | (species,) or (species, nzones) |
fixed composition or zone mass fractions, Fortran-ordered preferred |
input_mode |
selector | scalar | "value" for physical inputs, "log" for natural logs, "log10" for base-10 logs |
output |
selector | scalar | "raw" returns result arrays; "dict" returns named result arrays |
Returns:
| key | shape | meaning |
|---|---|---|
T |
(nzones,) |
temperature used by the wrapper |
Rho |
(nzones,) |
density used by the wrapper |
results |
(n_eos_results, nzones) |
raw eos result matrix when output="raw" |
result_names |
(n_eos_results,) |
row names for raw results; equal to mesa.EOS_RESULT_NAMES |
With output="dict", results[name] is a copied (nzones,) array for each
eos result name. Use raw output for throughput loops.
Fixed-composition example:
log_T = np.linspace(3.0, 8.0, 1000)
log_rho = np.linspace(-2.0, 8.0, 1000)
profile = mesa.Eos().dt_profile(log_T, log_rho, mix.chem_id, mix.xa, input_mode="log10")
i_gamma1 = mesa.EOS_RESULT_NAMES.index("gamma1")
gamma1 = profile["results"][i_gamma1, :]
mesa.eos_dt_profile_from_logs(...) and mesa.Eos().dt_profile_from_logs(...)¶
Signature:
mesa.eos_dt_profile_from_logs(
lnT: Iterable[float],
lnd: Iterable[float],
chem_id_values: Iterable[int],
xa: object,
) -> dict[str, object]
Compatibility alias for eos_dt_profile(..., input_mode="log"). Use this when
a saved model or caller already stores natural-log columns.
lnT = np.log(T)
lnd = np.log(rho)
profile = mesa.Eos().dt_profile_from_logs(lnT, lnd, mix.chem_id, mix.xa)
If the caller has base-10 logT and logRho, call the main profile function:
profile = mesa.Eos().dt_profile(logT, logRho, mix.chem_id, mix.xa, input_mode="log10")
mesa.eos_solve_rho(...) and mesa.Eos().solve_rho(...)¶
Signature:
mesa.eos_solve_rho(
T: float,
other: str | int,
other_value: float,
Rho_guess: float,
comp: Composition | Mapping[str, float] | Iterable[float] | None = None,
*,
logRho_tol: float = 1.0e-10,
other_tol: float = 1.0e-10,
max_iter: int = 100,
) -> dict[str, object]
Solves for density using MESA eosDT_get_Rho.
Inputs:
| argument | units | shape | meaning |
|---|---|---|---|
T |
K | scalar | fixed temperature |
other |
result name or index | scalar | eos result to match |
other_value |
MESA result units | scalar | target value for other |
Rho_guess |
g cm^-3 |
scalar | initial density guess |
logRho_tol |
log10(g cm^-3) |
scalar | density tolerance |
other_tol |
result units | scalar | target-result tolerance |
max_iter |
count | scalar | maximum solver iterations |
Returns Rho, logRho, eos_calls, and the full eos output dictionaries.
Example:
target = mesa.Eos().dt(T=1.0e7, Rho=1.0e2, comp=mix)
rho_solve = mesa.Eos().solve_rho(
T=1.0e7,
other="lnPgas",
other_value=target["lnPgas"],
Rho_guess=80.0,
comp=mix,
)
For lnPgas, pass the natural log of gas pressure, not total pressure.
mesa.eos_solve_t(...) and mesa.Eos().solve_t(...)¶
Signature:
mesa.eos_solve_t(
Rho: float,
other: str | int,
other_value: float,
T_guess: float,
comp: Composition | Mapping[str, float] | Iterable[float] | None = None,
*,
logT_tol: float = 1.0e-10,
other_tol: float = 1.0e-10,
max_iter: int = 100,
) -> dict[str, object]
Solves for temperature using MESA eosDT_get_T.
Inputs:
| argument | units | shape | meaning |
|---|---|---|---|
Rho |
g cm^-3 |
scalar | fixed density |
other |
result name or index | scalar | eos result to match |
other_value |
MESA result units | scalar | target value for other |
T_guess |
K | scalar | initial temperature guess |
logT_tol |
log10(K) |
scalar | temperature tolerance |
other_tol |
result units | scalar | target-result tolerance |
max_iter |
count | scalar | maximum solver iterations |
Returns T, logT, eos_calls, and the full eos output dictionaries.
mesa.eos_solve_rho_profile(...) and mesa.Eos().solve_rho_profile(...)¶
Signature:
mesa.eos_solve_rho_profile(
T: Iterable[float],
other: str | int,
other_value: Iterable[float] | float,
Rho_guess: Iterable[float] | float,
chem_id_values: Iterable[int],
xa: object,
*,
input_mode: str = "value",
logRho_tol: float = 1.0e-10,
other_tol: float = 1.0e-10,
max_iter: int = 100,
) -> dict[str, object]
OpenMP-batched profile version of eos_solve_rho(...). input_mode applies
to the known T profile. Rho_guess is always physical g cm^-3 and may be
scalar or (nzones,). Raw outputs include Rho, logRho, eos_calls,
results, d_dlnRho, d_dlnT, and d_dxa.
mesa.eos_solve_t_profile(...) and mesa.Eos().solve_t_profile(...)¶
Signature:
mesa.eos_solve_t_profile(
Rho: Iterable[float],
other: str | int,
other_value: Iterable[float] | float,
T_guess: Iterable[float] | float,
chem_id_values: Iterable[int],
xa: object,
*,
input_mode: str = "value",
logT_tol: float = 1.0e-10,
other_tol: float = 1.0e-10,
max_iter: int = 100,
) -> dict[str, object]
OpenMP-batched profile version of eos_solve_t(...). input_mode applies to
the known Rho profile. T_guess is always physical K and may be scalar or
(nzones,).
Output schemas¶
Use schema helpers to inspect expected field names, units, and shapes without calling MESA:
print(mesa.format_output_schema("eos_dt_full", species=mix.names))
print(mesa.format_output_schema("eos_dt_profile"))
Supported eos schema names are listed by:
mesa.output_schema_names()
Source mapping¶
$MESA_DIR/eos/public/eos_lib.f90
$MESA_DIR/eos/public/eos_def.f90
src/pyfortmesa/fortran/eos/mesa_eos_public.f90
src/pyfortmesa/mesa.py
src/pyfortmesa/mesa_support.py
Fortran wrappers:
mesa_eos_composition -> eosDT_get
mesa_eos_composition_full -> eosDT_get
mesa_eos_profile -> eosDT_get once per profile zone
mesa_eos_profile_from_logs -> compatibility wrapper for natural-log inputs
mesa_eos_solve_rho -> eosDT_get_Rho
mesa_eos_solve_rho_profile -> eosDT_get_Rho once per profile zone
mesa_eos_solve_t -> eosDT_get_T
mesa_eos_solve_t_profile -> eosDT_get_T once per profile zone
mesa_eos_shutdown -> free handle, optionally eos_shutdown
mesa_eos_sample_composition still exists as a legacy/sample Fortran wrapper,
but the public Python API uses named Composition objects instead.
Common mistakes¶
lnPgasis gas pressure, not total pressure.input_mode="log"means natural log; useinput_mode="log10"for base-10 arrays.- Scalar helpers accept
comp=mix; profile helpers requirechem_id_valuesandxa(species,)orxa(species, nzones). mesa.shutdown()belongs at the end of a driver, not inside a profile loop.
Not included¶
| MESA item | Reason |
|---|---|
eos_init, alloc_eos_handle, free_eos_handle |
Managed internally by pyfortmesa handles and mesa.shutdown(...). |
eos_ptr |
Exposes MESA pointer state; not safe or useful for normal Python calls. |
eos_get_control_namelist, eos_set_control_namelist |
Current control path is mesa.set_inlist(...); exposing raw namelist buffers is a larger API. |
eosPT_get and related eosPT_* routines |
Potentially useful, but not needed while eosDT_get_Rho/T cover the current inverse workflows. Add only with examples and tests. |
| gamma-law eos helper family | Specialized analytic eos path; not the same workflow as MESA table eos/kap calls. |
| HELM component/conversion helpers | Lower-level diagnostics; current API exposes the final MESA result vector. |
| Fermi-Dirac integral helper | Standalone numerical helper, not a pyfortmesa microphysics workflow yet. |
num_eos_files_loaded |
Debug/diagnostic only; can be added later if needed for table-loading diagnostics. |
mesa_eos_sample_composition |
Legacy/sample Fortran wrapper; prefer named Composition path for user code. |