htimer.f
230 lines · 1 definitions · on GitHub (7be4133)
Python version: htimer.py, 151 lines, on the right (switch to Python above the code).
Purpose
HTIMER sets the time step of the next model. Several criteria each propose a step, and it takes the most restrictive one (its comment): structure changes (PTIME: the change of $T$, $P$, $r$ and $L$ at any point since the previous model), angular-velocity changes for rotating models (WTIME: the largest fractional change of $\Omega$), hydrogen burning (XTIME: the hydrogen burnt in the core, or in the shell once the core is exhausted), helium burning (YTIME: the helium burnt at the temperature maximum) and, since 04/14, the motion of the model in the envelope-fitting "triangle" (ENTIME: the change of $\log T_\mathrm{eff}$ and $\log L$); and the step may not grow by more than a factor ATIME(13) from the previous one (default 1.5, "originally = 1.5" by PARMIN's comment; under its newer name TIME_MAX_DT_FRAC, also 1.5, when REMAP applies the newer names).
How it fits
- Who calls it: the main program, main.f: at the start of each kind card, and after each converged model to set the next step. main.f always passes $|\Delta t|$ after a model (
DELTS = DABS(DELTS)), and makes the step negative itself before a relaxation step. - Inputs: the previous step
DELTS(s); the model (HD,HL,HS1,HS2,HT,HP,HR,HCOMP,OMEGA,M,TEFFL);JCORE,JXMID,JXBEG(core and burning-shell indices);TLUMX(the luminosities by source, in solar units: elements 1–4 hydrogen burning, 5 helium burning, 7 the gravitational term); the ageDAGE(Gyr); the run numberNK. - Outputs: the new
DELTS(s),DELTSH(=DELTS, except on the relaxation branch, where it is left as passed unless the final-age cut applies),DDAGE(the step in years), andDWMAX(fromWTIME: the largest change in $\Omega$, used by the rotational-mixing routines to set their number of substeps). - Modules:
NMLPAR_MODholds the settings:ATIME(the step controls, formerly/CTLIM/); per run,SETDTfor a fixed step andENDAGEfor a final age, and the stop values for the central abundancesEND_DCEN,END_XCEN,END_YCEN(since 10/24, which is whyLENDAGalone no longer means a stop age);LPTIME(formerly/CT3/;HTIMERcan switch it off; default true, set byPARMIN's namelist or byREMAPfromLSTRUCT_TIME; main.f restores it at each solar-calibration cycle);LTRIST(the triangle governor, formerly/GOVS/) andLROT(formerly/ROT/).RUNLOOP_MODholds the per-run flagsLSETDT(fixed step) andLENDAG(final age); withSETDTandENDAGEthese were/SETT/, set byPARMINand shared with main.f,CALCAD,CHKSCAL,SETCAL,SETSCAL.CONSTANTS_MODgivesCSECYR(seconds per year).
The method
-
A negative
DELTSmeans the model is being relaxed, not evolved: skip to the end. -
A fixed step for this run (
LSETDT(NK)): $\Delta t$ =SETDT(NK)years, skip to the end. -
If $\log T_c > 7.1$ and the gravitational luminosity
TLUMX(7)is negative, switch the structure criterion off (LPTIME= false) for the rest of the job. Its comment is cut short ("this is done when"); the purpose is in REMAP's comment, "this is used only in the pre-MS and disabled for MS stars automatically," and in the documentation ofLSTRUCT_TIME, "disabled once Lgrav<0 (minimum radius, close to ZAMS)" (settled from the code and the documentation, Nov 9, 2026: lines 96–104↗; remap.f, lines 283–285↗). -
Collect the proposals, each $10^{20}$ s when not applicable or turned off: $\Delta t_P$ from
PTIME(ifLPTIME), $\Delta t_\Omega$ fromWTIME(if rotating), $\Delta t_H$ fromXTIME(if the H-burning luminosity exceeds $10^{-34}$), $\Delta t_{He}$ fromYTIME(likewise for He), $\Delta t_E$ fromENTIME(ifLTRISTand notLPTIME). The structure and rotation proposals ($\Delta t_P$, $\Delta t_\Omega$) below 1 s are replaced by $10^{20}$ ("a zero timestep in the model will fritz out the code"); the others are not checked (forENTIME, see bug 1). -
The new step: $$\Delta t = \min\left(f\,\Delta t_\mathrm{prev},\ \Delta t_H,\ \Delta t_{He},\ \Delta t_\Omega,\ \Delta t_P,\ \Delta t_E\right),\qquad f = \texttt{ATIME(13)},$$ leaving out the first term when $\Delta t_\mathrm{prev} \le 1$ s.
-
At the end: $\Delta t \leftarrow |\Delta t|$,
DDAGE$= \Delta t/$CSECYR; if the run stops at an age (LENDAG(NK)andENDAGE(NK)> 0), shorten the step so that the age does not passENDAGE(in years; the ageDAGEis in Gyr).
Design
The switch-off of LPTIME changes a module flag (a namelist setting) permanently, and is announced with a bare WRITE(*,…). A block of commented-out code ("Grant added") once tightened ATIME(5) and ATIME(6) with the helium luminosity.
From YREC's documentation
Physics Options (Timestep criteria): LTRIST "restricts the timestep during the Hertzsprung gap"; in the code it keeps the model from moving more than TRIDT in $\log T_\mathrm{eff}$ or TRIDL in $\log L$ in a step (the size of the envelope triangle), at any phase, when the structural criterion (LPTIME, LSTRUCT_TIME) is off. The step limits ATIME are documented under their newer names on REMAP's page; ENDAGE (Control Options) ends a run at an age.
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) A zero previous step passes through the envelope-triangle criterion.
(lines 158–162↗; lines 171–182↗; entime.f, lines 92–95↗) ENTIME returns DELTS/FAC with FAC $\ge 1/$ATIME(13), so a previous step of 0 (or under 1 s) gives an EDELT of at most ATIME(13) times it. Unlike PDELT and DELTSW (line 116↗; line 131↗), it is not replaced by $10^{20}$, and when the previous step is at most 1 s the minimum (line 181↗) takes it: The next step is again under 1.5 s, or 0 for every later model. This needs LTRIST (off by default) with LPTIME off.
A possible fix:
htimer.f
@@ lines 155–165 @@
C 04/14 JVS ADDED TIMESTEP GOVERNOR BASED ON THE SIZE OF THE ENVELOPE
C TRIANGLE. TIMESTEPS ARE RESTRICTED SUCH THAT THE MODEL DOES NOT MOVE
C MORE THAN TRIDL OR TRIDT
+C 11/09/26 KC via Claude
+C code changed to set the envelope-triangle timestep arbitrarily large
+C when it is below 1 s, as is done for PDELT and DELTSW.
IF(LTRIST .AND. .NOT. LPTIME) THEN
CALL ENTIME(DELTS,HL,TEFFL,M,EDELT)
ELSE
EDELT = 1.0D20
ENDIF
+ IF(EDELT.LT.1.0D0)EDELT=1.0D20
C LIMIT INCREASE IN TIME STEP FROM ONE MODEL TO THE NEXT FOR MODELS
C WITH A NON-ZERO TIMESTEP.
Checked by running YREC (Nov 9, 2026, the two 1 $M_\odot$ runs repeated on Nov 10 with a private start model; a line added at each suspected path counted how often it was taken, the outputs otherwise unchanged): The envelope-triangle step was computed in 10 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), up to 8,572 times per run (testsuite/Test_m1p0feh+0p0GS98_base_HeIgnite), always with LTRIST on and after LPTIME had been switched off. It came out below 1 s in one run only, a made-up one (testsuite/Test_m1p0feh+0p0GS98_base_HeIgnite with Reimers mass loss, LMDOT and LREIMER on), 919 times: The previous step was already 0.0020 to 0.0046 s, and EDELT, 0.0026 to 0.0060 s, kept the next one as small, so the star's age stayed at its starting 9.864 Gyr. That run stops with a convergence failure, with the fix or without it, after the same 919 models at the same age; the harness finds the track and the stored model identical, and the track does not differ at any common age. The fix does not change how the run ends. Intent: The guard after PTIME and WTIME says "A ZERO TIMESTEP IN THE MODEL WILL FRITZ OUT THE CODE" (lines 114–116↗); the EDELT line, added later ("04/14 JVS"), has none.
Definitions
subroutineHTIMER
Minimum over the step criteria (above), with fixed-step, relaxation and final-age special cases.
Uses modules CONSTANTS_MOD, DIMENSIONS_MOD, NMLPAR_MOD, RUNLOOP_MOD
Called by (file level) ×2
Flowchart of its calls, in order (5)
Change log
The changes since rp_1
Changed since rp_1. Declarations only: COMMON blocks to modules, IMPLICIT NONE; the unused /CONST/ and /FLAG/ are gone.