getnewenv.f
326 lines · 1 definitions · on GitHub (7be4133)
Python version: getnewenv.py, 277 lines, on the right (switch to Python above the code).
Variables on this page (32)
c4pil, cc23, cgl, cln, clsunl, csigl, envbeg, envd, envmax, envmin, envp, envr, envs, envt, envx, envz, hpttol, json, lcenv, ldh, lexcom, lrot, numenv, senv, spotf, spotx, stotal, walpcz, xxdh, yydh, zdh, zzdh
Purpose
GETNEWENV moves the outer fitting point of the interior model outward, by turning part of the envelope into new interior points, so that the envelope again holds the fraction of the mass it held before the step's mass change ($\log(m_\mathrm{fit}/M)$ = SENVOLD). Its header (MHP 07/02): "move the outer fitting point when the total mass is being decreased; add new points by dropping a sinkline from the surface down and including new points up to the desired envelope mass." It integrates the envelope once from the surface, then copies the points between the old and the new fitting point into the model.
When it runs. The main program calls it when MASSLOSS has set LNEWFIT, which it does whenever its rate DMDT is positive (massloss.f line 131), whichever rate applies: the constant DMDT0 or the Reimers rate CREIM$\,L/(gR)$. MDOT adds DELM = DMDT$\cdot\Delta t$ to the total mass, so a positive DMDT raises $M$ while the interior points keep their masses, and the envelope above the last point grows; main.f's comment reads "restore prior fitting point if mass accretion is being included." The defaults of both rates are negative (DMDT0 = $-10^{-14}$, CREIM = $-4\times10^{-13}$, parmin.f), so with them the routine is not called; the header's "mass is being decreased" disagrees with this trigger.
How it fits
- Who calls it: only the main program (main.f), when
LNEWFITis set (above); it then calls FPFT with its ownOMEGA. - Inputs:
SENVOLD(the desired fitting point, below); the model arrays (HCOMP,HD,HL,HP,HR,HS,HT,LC,M), the surfaceBL($\log L/L_\odot$) andTEFFL, the rotation arrays, andCMIXL, the mixing-length parameter, passed on toENVINT. - What it calls: ENVINT (the envelope integration) and, for rotating models, GETROT.
-
Outputs: the model with
Mincreased and the new points filled;HS1,HS2(unlogged masses and shell masses) for the new points; for rotating models,HJM,HI,ETA2,QIW,R0,HKEROT(notOMEGA, which is local: suspected bug 1) and the totalsSJTOT,SKEROT;LNEW= true;SENVinCOMP_MOD. It prints the new points to standard output. -
Modules:
ENVSTRUCT_MOD(the envelope solutionENVP,ENVT,ENVS,ENVD,ENVR,ENVX,ENVZ,LCENV,NUMENV, written byENVINT);NMLPAR_MOD(the envelope step sizesENVMAX,ENVMIN,ENVBEG, temporarily set toHPTTOL(8)and restored; the starspot parametersSPOTF,SPOTX;LROT,WALPCZ;LEXCOM);COMP_MOD(STOTAL= $\log M$,SENV);DEBHU_MOD(the Debye–Hückel composition, set here from the surface shell);CONSTANTS_MOD;DIMENSIONS_MOD(JSON).
The method
-
Surface quantities. From $L = 4\pi R^2\sigma T_\mathrm{eff}^4$ and $g = GM/R^2$: $$\log R = \tfrac12\left(\log\frac{L}{L_\odot} + \log L_\odot - 4\log T_\mathrm{eff} - \log 4\pi - \log\sigma\right), \qquad \log g = \log G + \log M - 2\log R.$$ With spots (fraction $f$ =
SPOTF, temperature ratio $x$ =SPOTX) and a convective surface, the ambient temperature is $\log T_\mathrm{amb} = \log T_\mathrm{eff} - \tfrac14\log(f x^4 + 1 - f)$. -
Envelope integration from the surface down to the current fitting point with
ENVINT, at the spacingHPTTOL(8), without rotational distortion ($f_P = f_T = 1$). - Matching. The envelope's first point is at the mass of the last interior point; the differences there in $\log P$, $\log\rho$, $\log T$, $\log r$ are added to all envelope points, which shift down by one (the convective flag
LCENVwith them), and points closer than $10^{-10}$ in $\log m$ are dropped. -
New points. Each envelope point below the new fitting point becomes an interior point, with $L$ held at its value at the old fitting point and the abundances other than $X$ and $Z$ copied from it (lines 184–201↗). The copy matches the envelope: ENVINT integrates it with the surface $X$ and $Z$ of shell
Mat every point (ENVX,ENVZ: lines 112–113↗, envint.f, lines 633–634↗, envint.f, lines 760–761↗), so the whole envelope has the old fitting point's composition (settled from the code, Nov 9, 2026). The last point is interpolated linearly in $\log m$ to the new fitting point. -
Shell masses. $m = 10^{\log m}$, $\Delta m_j = \tfrac12(m_{j+1} - m_{j-1})$, and the last shell takes the rest of the star.
- Rotation. The new points get, as a first guess, constant $j$ if $\alpha$ =
WALPCZ$\le -2$, solid body if $\alpha \ge 0$, and otherwise $\Omega \propto r^{\alpha}$, the lawWCZIMPimposes (PARMIN limits $\alpha$ to $[-2, 0]$); with $I = \tfrac23 r^2$ and $j = \Omega I$.GETROTthen finds the rotation law, and the totals $J = \sum j\,\Delta m$ and $E_\mathrm{rot} = \sum\tfrac12\Omega j\,\Delta m$ are recomputed.
SENV is the fitting point's $\log(m/M)$, as can be read from HS = ENVS + STOTAL; it is limited to at most $-10^{-12}$.
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) OMEGA is a local array.
(lines 74–75↗; lines 281–299↗; line 300↗) OMEGA is not an argument: It is declared in DIMENSION and is local. In step 6, the solid-body and general cases read OMEGA(MM), which is never set in this routine before (it keeps whatever an earlier call left, or its initial value at the first call), so the new points' $j$ (HJM(J) = OMEGA(MM)*HI(J), or through W0) comes from that stale value. Then GETROT overwrites the local OMEGA and the result is used only for $E_\mathrm{rot}$, while the main program goes on to call FPFT with its own OMEGA, which has no values for the new points (main.f, lines 1040–1045↗). What follows: wrong specific angular momentum for the accreted shells and wrong $f_P$, $f_T$ there until the next GETROT. Only with rotation (LROT) and a positive mass-change rate (both off by default); with them, the default WALPCZ = 0 takes the solid-body case.
A possible fix:
getnewenv.f
@@ lines 6–12 @@
SUBROUTINE GETNEWENV(SENVOLD,HCOMP,HD,HL,HP,HR,HS,HS1,HS2,
C * HSTOT,HT,LC,ETA2,HG,HI,HJM,QIW,R0, ! KC 2025-05-31
* HSTOT,HT,LC,ETA2,HI,HJM,QIW,R0,
- * HKEROT,BL,SJTOT,SKEROT,TEFFL,M,LNEW,CMIXL)
+ * HKEROT,BL,SJTOT,SKEROT,TEFFL,M,LNEW,CMIXL,
+ * OMEGA)
+C 11/09/26 KC via Claude
+C code changed to take OMEGA from the main program as an argument; the
+C local array was read at OMEGA(MM) before it was set, and the values
+C GETROT gives it did not reach the main program's FPFT.
C 10/15/26 MHP via Claude
C code changed to take JSON from DIMENSIONS_MOD instead of declaring
C PARAMETER(JSON=5000) here.
main.f (another file)
@@ lines 1040–1046 @@
CALL GETNEWENV(SENVOLD,HCOMP,HD,HL,HP,HR,HS,HS1,HS2,
C * HSTOT,HT,LC,ETA2,HG,HI,HJM,QIW,R0, ! KC 2025-05-31
* HSTOT,HT,LC,ETA2,HI,HJM,QIW,R0,
- * HKEROT,BL,SJTOT,SKEROT,TEFFL,M,LNEW,CMIXL)
+ * HKEROT,BL,SJTOT,SKEROT,TEFFL,M,LNEW,CMIXL,
+ * OMEGA)
C CALCULATE FP AND FT GIVEN OMEGA FOR THE NEW POINT DISTRIBUTION
CALL FPFT(HD,HR,HS,M,OMEGA,ETA2,FP,FT,HG,R0)
LNEWFIT = .FALSE.
with OMEGA added at the end of the call in main.f (line 1043).
Checked by running YREC (Nov 9, 2026; a line added at each suspected path counted how often it was taken, the outputs otherwise unchanged): GETNEWENV ran in none of 34 runs (26 of YREC's cases, from a 0.04 $M_\odot$ brown dwarf and the solar models to 9 $M_\odot$, rotation, and helium burning, and 8 made-up ones; one of these, with FCORE = 1.0, stopped in its first second). Two made-up runs had mass loss on (LMDOT and LREIMER), but the routine runs only for a mass gain (DMDT > 0, massloss.f, lines 131–132↗), which no case or document sets. A rotating run with LMDOT and DMDT0 > 0 would reach it; none was run. No fix was run. Intent: none found.
2. (not reached) A sign error in the interpolation of $X$ and $Z$.
(lines 217–218↗) When the new fitting point lies between the last interior point and the first envelope point, HCOMP(1,J) = HCOMP(1,M)+FX*(HCOMP(1,M)-ENVX(JM)), and the same for $Z$. Every other interpolation is $a + f(b - a)$; this one is $a + f(a - b)$. Harmless today: ENVX and ENVZ hold the surface X, Z, which are HCOMP(1,M), HCOMP(3,M) (step 4), so the difference is zero. It would matter once the envelope's composition varied.
A possible fix:
getnewenv.f
@@ lines 214–221 @@
HR(J) = HR(M)+FX*(ENVR(JM)-HR(M))
HS(J) = X1
HT(J) = HT(M)+FX*(ENVT(JM)-HT(M))
- HCOMP(1,J) = HCOMP(1,M)+FX*(HCOMP(1,M)-ENVX(JM))
- HCOMP(3,J) = HCOMP(3,M)+FX*(HCOMP(3,M)-ENVZ(JM))
+C 11/09/26 KC via Claude
+C code changed to interpolate X and Z from the last interior point
+C toward the envelope point, as for the other quantities.
+ HCOMP(1,J) = HCOMP(1,M)+FX*(ENVX(JM)-HCOMP(1,M))
+ HCOMP(3,J) = HCOMP(3,M)+FX*(ENVZ(JM)-HCOMP(3,M))
DO K = 4,JEND
HCOMP(K,J) = HCOMP(K,M)
END DO
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, as for suspected bug 1: GETNEWENV runs only for a mass gain (DMDT > 0, massloss.f, lines 131–132↗), and no run gained mass. No fix was run. Intent: none found.
Definitions
subroutineGETNEWENV
Moves the fitting point outward after mass loss: integrates the envelope from the surface, matches it to the last interior point, adds the envelope points as new shells, and resets rotation for them (method above).
Uses modules COMP_MOD, CONSTANTS_MOD, DEBHU_MOD, DIMENSIONS_MOD, ENVSTRUCT_MOD, NMLPAR_MOD
Called by (file level)
Flowchart of its calls, in order (2)
Change log
The changes since rp_1
Changed since rp_1. CMIXL is a new argument, passed on to ENVINT (it was in /CONST3/); COMMON blocks to modules (the namelist parameters from /INTENV/, /CTOL/, /SPOTS/, /ROT/ and /FLAG/ now come from NMLPAR_MOD; the unused /ENVPRT/ dropped), IMPLICIT NONE. No question is settled.
Changed since a8a5950. The shift of the envelope points moves LCENV with the other arrays, so the new points' convective flags are no longer read one point off; the general rotation case follows $\Omega = C\,r^{\alpha}$, as WCZ does, rather than $\Omega\,r^{\alpha}$ constant (settles former question 7).