equal_to_model.f
144 lines · 1 definitions · on GitHub (7be4133)
Python version: equal_to_model.py, 128 lines, on the right (switch to Python above the code).
Purpose
EQUAL_TO_MODEL ends a step of gravitational settling (microscopic diffusion): the diffusion equations are solved on an equally spaced grid in radius, and this routine applies the resulting changes in hydrogen (and, with metal diffusion, in $Z$) to the model's own points. It then converts the model's arrays back from the dimensionless units used by the diffusion solver.
How it fits
- Who calls it: only GRSETT, at the end of the settling step; MODEL_TO_EQUAL does the opposite transformation at its start. MICRODIFF_ETM has the same unit conversion for the newer diffusion scheme.
- Inputs: the equally spaced radii
ER(NPTpoints) and the changesEXin $X$ on them; the rangeIBEGIN..IENDof model points inside the grid; the model arraysHCOMP,HRU(radius),HTU(temperature),HS1(mass),HQPR, the time stepDTand the total massSTOT, all in the solver's units. - What it calls: INTRP2, four-point Lagrange weights.
- Outputs:
HCOMPupdated, andHRU,HTU,HS1,HQPR,DT,STOTback in physical units. - Modules:
CONFAC_MODholds the conversion factorsCON_RAD,CON_MASS,CON_TEMP,CON_TIME, set by MICRODIFF_SETUP andSETUP_GRSETT;GRAVEZ_MODholds the change in $Z$ on the grid,EZ(withGRSETT,MODEL_TO_EQUALand the Lax–Wendroff routines, which use its other entries; this routine reads onlyEZ);NMLPAR_MODgives the flagLDIFZ(formerly in/GRAVS3/);DIMENSIONS_MODgives the array sizeJSON.
The method
-
Inside the grid (
IBEGIN< $i$ <IEND): for each model point, find the four grid points around its radius, get Lagrange weights $b_k$, and $$\Delta X_i = \sum_{k=1}^{4} b_k\,\Delta X(r_k), \qquad X_i \leftarrow \min(X_i + \Delta X_i,\; 1 - Z_i - X_{3,i}),$$ where $X_3$ is $^3$He (HCOMP(4,·)). With metal diffusion, $Z$ changes the same way, and every metal species (rows 5–11) is scaled by $Z_\mathrm{new}/Z_\mathrm{old}$. Helium takes the rest: $Y = 1 - X - Z - X_3$. The scaling divides by the old $Z$ (suspected bug 1). The lineIF (J .EQ. 0) PRINT*, 'line 47 etm'(line 69↗) cannot fire, sinceJstarts atJMIN≥ 2 (unused?); nor canIF (K0 .EQ. 0) K0=1(lines 76–77↗), sinceNPTis at least 4 (unused?). -
Below the grid ($i \le$
IBEGIN) the change at the first grid point is applied; above it ($i \ge$IEND), the change at the last. The pointsIBEGINandIENDare themselves the grid's end points:MODEL_TO_EQUALputs the first grid point atHRU(IBEGIN)and spaces the grid so that the last falls atHRU(IEND), with the model's values there (settled from the code, Nov 9, 2026: lines 42–44↗, lines 113–116↗; model_to_equal.f, line 73↗, model_to_equal.f, lines 195–198↗, model_to_equal.f, lines 205–206↗, model_to_equal.f, lines 266–267↗). The comment explains the guards: "because metals sink, and hydrogen rises, the failsafes are opposite" ($X \ge 0$ and $Z \le Z_\mathrm{max}$ below; $X \le X_\mathrm{max}$ and $Z \ge 0$ above). - Units: $r \leftarrow r/c_r$, $T \leftarrow T/c_T$, $m \leftarrow m/c_m$,
HQPR$\leftarrow$HQPR$\cdot c_r$, $\Delta t \leftarrow \Delta t\,c_t$, $M \leftarrow M/c_m$.
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. (not reached) Division by $Z$.
(line 52↗; line 103↗; line 122↗) With metal diffusion, each shell's metal species are scaled by ZZ2 = ZZ/HCOMP(3,I), the new $Z$ over the old; a shell with $Z = 0$ divides by zero, and rows 5–11 become NaN (or infinite). What follows: A metal-free model (Population III) cannot be run with LDIFZ. Only with LDIFZ (off by default) and LNEWDIF false, in a shell with $Z = 0$.
A possible fix (the same at lines 103 and 122):
equal_to_model.f
@@ lines 49–55 @@
DO I = IBEGIN,1,-1
ZMAX = 1.0D0 - HCOMP(1,I) - HCOMP(4,I)
ZZ=MIN(HCOMP(3,I)+EZ(1),ZMAX)
- ZZ2 = ZZ/HCOMP(3,I)
+C 11/09/26 KC via Claude
+C code changed to leave the metal species unscaled where Z was zero.
+ IF(HCOMP(3,I).GT.0.0D0)THEN
+ ZZ2 = ZZ/HCOMP(3,I)
+ ELSE
+ ZZ2 = 1.0D0
+ ENDIF
HCOMP(3,I) = ZZ
DO J = 5,11
HCOMP(J,I) = ZZ2*HCOMP(J,I)
@@ lines 100–106 @@
DZMOD = FACINTERP(1)*EZ(K0)+FACINTERP(2)*EZ(K0+1)+
* FACINTERP(3)*EZ(K0+2)+FACINTERP(4)*EZ(K0+3)
ZZ = MIN(HCOMP(3,I)+DZMOD,ZMAX)
- ZZ2 = ZZ/HCOMP(3,I)
+C 11/09/26 KC via Claude
+C code changed to leave the metal species unscaled where Z was zero.
+ IF(HCOMP(3,I).GT.0.0D0)THEN
+ ZZ2 = ZZ/HCOMP(3,I)
+ ELSE
+ ZZ2 = 1.0D0
+ ENDIF
HCOMP(3,I)=ZZ
DO J = 5,11
HCOMP(J,I) = ZZ2*HCOMP(J,I)
@@ lines 119–125 @@
ZMIN = 0.0D0
DO I = IEND,M
ZZ = MAX(HCOMP(3,I)+EZ(NPT),ZMIN)
- ZZ2 = ZZ/HCOMP(3,I)
+C 11/09/26 KC via Claude
+C code changed to leave the metal species unscaled where Z was zero.
+ IF(HCOMP(3,I).GT.0.0D0)THEN
+ ZZ2 = ZZ/HCOMP(3,I)
+ ELSE
+ ZZ2 = 1.0D0
+ ENDIF
HCOMP(3,I) = ZZ
DO J = 5,11
HCOMP(J,I) = ZZ2*HCOMP(J,I)
Checked by running YREC (Nov 9, 2026; a line added at each suspected path counted how often it was taken, the outputs otherwise unchanged): not reached in any of 34 runs (26 of YREC's cases, from 0.04 to 9 $M_\odot$, with rotation, settling, and helium burning, and 8 made-up ones). These lines belong to the old settling routines (LNEWDIF false), which no case uses: Every case with settling sets LNEWDIF and LDIFLI, and the documentation lists LNEWDIF among the legacy options (docs/source/namelist_physics.md, line 285). Reaching them takes LDIFY or LDIFZ with LNEWDIF false and LDIFLI off, since LDIFLI forces LNEWDIF on (parmin.f, lines 1239–1251↗), and in addition a shell with $Z = 0$; no case has a metal-free model. Intent: none found.
Definitions
subroutineEQUAL_TO_MODEL
Interpolates the settling changes in $X$ (and $Z$) from the equally spaced grid to the model points with four-point Lagrange weights, enforces the composition limits, and converts the model back to physical units.
Uses modules CONFAC_MOD, DIMENSIONS_MOD, GRAVEZ_MOD, NMLPAR_MOD
Called by GRSETT
Flowchart of its calls, in order (1)
Change log
The changes since rp_1
Changed since rp_1. Declarations only: COMMON blocks to modules, IMPLICIT NONE.