PyREC scaffolding (from YREC development, 7be4133)/ eqscve.fGlossary

eqscve.f

474 lines · 1 definitions · on GitHub (7be4133)

Python version: eqscve.py, 305 lines, on the right (switch to Python above the code).

Variables on this page (11)

cln, idp, idtscv, nptsx, nts, tablenv, tablex, tabley, tlogx, xenv, zenv

Purpose

EQSCVE interpolates the Saumon–Chabrier–Van Horn (SCV) equation of state in its table for the surface (envelope) composition. It returns the density, the thermodynamic derivatives and the ionization fractions of hydrogen and helium. For any other composition it hands the work to EQSCVG, which combines the pure-hydrogen, pure-helium and metal tables.

How it fits

  • Who calls it: only EQSTAT2, when LSCV is set and $\log T <$ TSCUT, right after EQSAHA. If the point is outside the table (LCALC false), the routine returns without touching its outputs, so the EQSAHA values stand.

  • Inputs: TL, T, P, BETA, X, Z. It compares X, Z with XENV, ZENV from /COMP/.

  • What it calls: KSPLINE and KSPLINT (a four-point natural spline), INTERP (four-point Lagrange) and EQSCVG.
  • Outputs: DL, D, QDT, QDP, QCP, DELA, FXION, LCALC.
  • Modules: SCVEOS_MOD holds the tables (TLOGX, TABLENV for the envelope mixture, TABLEX, TABLEY, TABLEZ, SMIX, NPTSX) and the last indices IDTSCV, IDP; it is filled by SETSCV and used also by EQSCVG and SETUPS. The flag LSCV is now in NMLPAR_MOD. COMP_MOD gives the envelope composition; CONSTANTS_MOD the constants.

The method

  1. The table is in $\log T$ and $\log P_\mathrm{gas}$, with $P_\mathrm{gas} = \beta P$. Out of table if $\log T$ is outside TLOGX, if $\log P_\mathrm{gas} < 4$, or if it is above the last pressure of the stencil's lowest-temperature row.
  2. Find the 4×4 stencil (IDTSCV, IDP), starting from the last one. For each of the 4 temperatures, a natural spline in $\log P_\mathrm{gas}$ gives five quantities (columns 2–6 of TABLENV: $\log\rho$, $Q_{\rho T}$, $Q_{\rho P}$, $c_P$, $\partial U/\partial T$); a second spline in $\log T$ gives their values at the point. Column 5, the tabulated $c_P$ (TEMPT(4), QCP0), is interpolated but never used, since step 4 rebuilds $c_P$ from $\partial U/\partial T$: unused? (line 384↗).

    One pressure grid serves all four temperatures. The pressure abscissae are always taken from the row IDTSCV, the lowest temperature of the stencil, also for the other three rows (lines 102–103↗; lines 164–166↗), and the ionization step (5) uses TABLENV's pressures, which are TABLEX's (setscv.f, line 165↗), for TABLEX and TABLEY too (lines 407–409↗). That is right: In input/eos/scv, every row of h_tab_i.dat and he_tab_i.dat (63 temperatures) is a prefix of one grid, $\log P_\mathrm{gas} = 4.00$, $4.20$, …, its length growing with $T$ from 30 to 76 points, so the row IDTSCV is the shortest of the stencil and its pressures are those of the three hotter rows; the metal table z_tab_i.dat, read in reverse order (setups.f, lines 388–389↗), has the same pressures row by row (checked from the files, Nov 10, 2026).

  3. Smoothing at stencil changes. When the point is within TOLST = 0.032 in $\log T$ (or TOLSP = 0.08 in $\log P$) of the edge of the middle interval, the routine also interpolates on the stencil shifted by one, and blends the two linearly (FST, FSP), so that the result does not jump when the stencil changes.

  4. Radiation. The tables hold the gas alone. With $Q_{\rho P,0}$ and $Q_{\rho T,0}$ from the table, $$Q_{\rho P} = \frac{Q_{\rho P,0}}{\beta},\qquad \chi_T = \beta\left(-\frac{Q_{\rho T,0}}{Q_{\rho P,0}}\right) + 4(1-\beta),\qquad Q_{\rho T} = -\chi_T\,Q_{\rho P},$$ $$\frac{\partial U}{\partial T} \mathrel{+}= \frac{4}{T}\cdot\frac{3P_\mathrm{rad}}{\rho},\qquad c_P = \frac{\partial U}{\partial T} - \frac{P}{\rho T}Q_{\rho T}\chi_T,\qquad \nabla_\mathrm{ad} = -\frac{P\,Q_{\rho T}}{\rho T\,c_P}.$$

  5. Ionization. From the pure-hydrogen table TABLEX and the pure-helium table TABLEY (columns 2 and 3, Lagrange interpolation on the same stencil and pressure abscissae as TABLENV), the particle fractions of H$_2$, H, He and He$^+$; charge and particle conservation give the rest, and $$x_{\mathrm{H}^+} = \frac{n_{\mathrm{H}^+}}{n_{\mathrm{H}_2} + n_\mathrm{H} + n_{\mathrm{H}^+}}, \quad x_{\mathrm{He}^+} = \frac{n_{\mathrm{He}^+}}{n_\mathrm{He} + n_{\mathrm{He}^+} + n_{\mathrm{He}^{++}}},$$ and likewise for He$^{++}$ (the code's formula for H$^+$; see bug 1).

Suspected bugs, checked by running the code

Each bug is marked by what running the code showed: (changes results, large) or (small), the fix moving a run clearly beyond a null change; (stops the run); (wrong output), the fix changing only what is written; (harmless in the runs), within the noise; (never occurred), the code ran but the fault did not; (not reached); (cannot be reached), a guard prevents it; (withdrawn), the suspicion was wrong.

1. (harmless in the runs) H$_2$ counted as one hydrogen nucleus.

(line 463↗; setscv.f, lines 58–59↗) In step 5 the denominator XTF_H2 + XTF_H1 + XTF_HP counts each H$_2$ molecule once, but it holds two hydrogen nuclei, and the comment says the result is "the fraction XHP of hydrogen nuclei that are singly ionized" (line 460↗). SETSCV counts the nuclei with the factor 2 for the same table columns (its 1+3*TABLEX(I,J,2)+TABLEX(I,J,3) is twice $2x_{\mathrm{H}_2} + x_\mathrm{H} + x_{\mathrm{H}^+}$). So FXION(1) is too large wherever H$_2$ is present; it is read by the conductive opacity (condopacpint.f, line 39↗) and written to the outputs. Where H$_2$ is abundant, few H nuclei are ionized, so the absolute error is probably small; not traced. Only with LSCV (off by default, nmlpar_mod.f, line 258↗).

A possible fix:

eqscve.f

@@ lines 460–466 @@
 C We are seeking the fraction XHP of hydrogen nuclei that are singly ionized,
 C the fraction XHeP of helium huclei that are singly ionized and XHePP, the
 C helium fraction that is doubly ionized.
-      XHP = XTF_HP / (XTF_H2 + XTF_H1 + XTF_HP)
+C 11/09/26 KC via Claude
+C code changed to count the two hydrogen nuclei of each H2 molecule.
+      XHP = XTF_HP / (2D0*XTF_H2 + XTF_H1 + XTF_HP)
       XHeP = XTF_HeP / (XTF_He + XTF_HeP + XTF_HePP)
       XHePP = XTF_HePP / (XTF_He + XTF_HeP + XTF_HePP)

Checked by running YREC (Nov 9, 2026; a line added at each suspected path counted how often it was taken, the outputs otherwise unchanged). The path was taken in 32 of the 34 cases run, from 28,366 to 40,729,900 times, at $\log T$ from 3.40 to 6, and H$_2$ was present (the condition) in all 32, with a molecular fraction up to 0.80: in testsuite/Test_m0p3feh+0p0GS98_scv_ZAMS, for example, at 1,175,356 of 1,319,735 calls. With the page's fix, that case's track moves by at most $10^{-11}$ in $\log L$, against $10^{-9}$ for a null change (nearly every opacity, all with $3 \le \log T \le 9$ and $-6 \le \log\rho \le 9.75$, times $1 + 10^{-10}$), with the same 259 models and end age; in testsuite/Test_m0p95feh+0p0_GN93_TAHB, $\log L$ moves by at most $3\times10^{-8}$ dex and $\log T_\mathrm{eff}$ by $10^{-7}$, against $1.67\times10^{-7}$ and $1.54\times10^{-8}$ for a null change, with the same 966 models and end age. Both runs' .short and .store files differ beyond 2%, which YREC's iterations make likely for almost any change. So the fix moves these tracks by no more than $10^{-7}$ dex, at the level of the noise. Intent: none found. The same miscount in eqscvg.f, suspected bug 1 changes a 0.04 $M_\odot$ track well beyond the noise, so a run whose envelope composition reaches such layers could show it here.

Definitions

subroutineEQSCVE

lines 5–474 · GitHub

SCV equation of state at the envelope composition: 2D spline interpolation with smoothing at stencil changes, radiation added, ionization fractions from the H and He tables (method above). Hands other compositions to EQSCVG.

Uses modules COMP_MOD, CONSTANTS_MOD, SCVEOS_MOD

Called by EQSTAT2 ×5

Flowchart of its calls, in order (19)

Change log

The changes since rp_1

Changed since rp_1. Declarations (COMMON blocks to modules, IMPLICIT NONE); the saved temperature index IDT is renamed IDTSCV in SCVEOS_MOD, and the unused /NMLPAR/ declaration is removed. The arithmetic is unchanged.