1CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
2C GETTAU C
3C G Somers, 3/17 C
4CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
5C SUBROUTINE GETTAU(HCOMP,HR,HP,HD,HG,HS1,HT,FP,FT,TEFFL,HSTOT,BL,M, ! KC 2025-05-31
6 SUBROUTINE GETTAU(HCOMP,HR,HP,HD,HS1,HT,FP,FT,TEFFL,HSTOT,BL,M,
7 * * LC,RBCZ,CMIXL)
8C 10/15/26 MHP via Claude
9C code changed to take JSON from DIMENSIONS_MOD instead of declaring
10C PARAMETER(JSON=5000) here.
11 USE DIMENSIONS_MOD
12C 10/14/26 MHP via Claude
13C code changed to convert COMMON/SCRTCH/ into SCRTCH_MOD.
14 USE SCRTCH_MOD
15C 10/14/26 MHP via Claude
16C code changed to convert COMMON/OVRTRN/ into OVRTRN_MOD.
17 USE OVRTRN_MOD
18C 10/14/26 MHP via Claude
19C code changed to convert COMMON/ENVSTRUCT/ into ENVSTRUCT_MOD.
20 USE ENVSTRUCT_MOD
21C 10/14/26 MHP via Claude
22C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
23 USE NMLPAR_MOD
24C 10/14/26 MHP via Claude
25C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
26 USE CONSTANTS_MOD
27C 10/20/26 MHP via Claude
28C code changed to replace implicit typing with IMPLICIT NONE and
29C explicit declarations.
30 IMPLICIT NONE
31 REAL*8 ATEFFL,B,BL,CHKPRS,CMIXL,DELF1,DELF2,FP,FPL,FT,FTL,GL,
32 * * HCOMP,HCOMPF,HD,HDF,HGF,HP,HPF,HR,HRF,HS1,HSF,HSTOT,HT,HTF,
33 * * HVF,PLIM,RBCZ,RL,TEFFL,X,Z
34 INTEGER I,IDUM,IMAX,IXX,J,M,MM
35 LOGICAL*4 LALLCZ,LC,LCF,LPRT,LPULPT,LSBC0
36C 10/13/26 MHP via Claude: removed the unused COMMON/IOUNITS/ declaration
37C (no member referenced here; residue of the obsolete-option removals).
38C 10/12/26 MHP via Claude
39C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
40C namelist variables that the physics routines read from 27 COMMON
41C blocks which also held derived or working members. Those blocks keep
42C only their non-namelist members; five of them -- NEWMX, VMULT,
43C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
44C Derivation-only namelist variables from the same blocks went to
45C COMMON/NMLBYPASS/ instead, not here.
46C
47C Declared identically in all 121 files that hold any of these members.
48C Generated from one member list, so every copy is byte-identical; the
49C linker's 'size of symbol changed' warning is the check that they are.
50C 9/25/26 MHP via Claude
51C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
52C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
53C KC 2025-05-30 reordered common block elements
54C JvS 08/25 Updated with new elements
55C DIMENSION HCOMP(15,JSON),HR(JSON),HP(JSON),HD(JSON),HG(JSON),HS1(JSON), ! KC 2025-05-31
56 DIMENSION HCOMP(15,JSON),HR(JSON),HP(JSON),HD(JSON),HS1(JSON),
57 * * HT(JSON),FP(JSON),FT(JSON),HCOMPF(15,JSON),HRF(JSON),HPF(JSON),
58 * * HDF(JSON),HSF(JSON),HTF(JSON),LC(JSON),HGF(JSON),HVF(JSON),
59 * * DELF1(JSON),DELF2(JSON),LCF(JSON)
60 REAL*8 DUM1(4),DUM2(3),DUM3(3),DUM4(3)
61 INTEGER*4 KATM, KENV, KSAHA
62 SAVE
63C
64C This routine devises a new, systematic method for determining the
65C convective overturn timescale. It will calculate the overturn timescale
66C one pressure scale height above the BCZ for whichever of the following three
67C conditions holds.
68C
69C 1) 1 PSCA above the BCZ is in the interior model.
70C 2) 1 PSCA above the BCZ is in the envelope model.
71C 3) The BCZ is in the interior, but 1 PSCA above is in the envelope.
72C
73C If none of these are satisfied, TAUCZ is set to 0.0.
74C
75C If 1): Call ENVINT to determine PPHOT, TAUINT(NEW) to determine TAUCZ
76C If 2): Call ENVINT to determine PPHOT, which calls TAUCAL for TAUCZ.
77C If 3): Stitch together interior and envelope.
78
79 TAUCZ = 0.0
80 PPHOT = 0.0
81
82C Check if 1 PSCA above BCZ is within envelope. If so, only the interior
83C model should be considered for TAUCZ. Set LCALCENV = .FALSE.. If not,
84C have ENVINT calculate the full structure, and stitch the envelope
85C and interior together.
86C
87C Determine where the BCZ is.
88 DO 71 I = M-1,1,-1
89 IF(.NOT.LC(I)) GOTO 81
90 71 71 CONTINUE
91 LALLCZ = .TRUE.
92 I = 0
93 81 81 IMAX = I + 1
94C Compare the pressure there to the surface pressure.
95 CHKPRS = HP(IMAX)-HP(M)
96C IF CHKPRS > 1.0, AT LEAST 3 PSCAS, SO LOOK INTERIOR.
97C IF CHKPRS < 1.0, 1 PSCA UP MIGHT BE IN ENV. STITCH TOGETHER.
98C FINALLY, IF LNEWTCZ = .FALSE., MAKE SURE TO CALC AN ENV.
99 IF(CHKPRS.LT.1.0.OR..NOT.LNEWTCZ)THEN
100 LCALCENV = .TRUE.
101 ELSE
102 LCALCENV = .FALSE.
103 ENDIF
104C
105C CALL ENVINT
106C
107 FPL = FP(M)
108 FTL = FT(M)
109 IDUM = 0
110 B = DEXP(CLN*BL)
111 KATM = 0
112 KENV = 0
113 KSAHA = 0
114 IXX=0
115 LPRT=.TRUE.
116 LSBC0 = .FALSE.
117 LPULPT = .FALSE.
118 X = HCOMP(1,M)
119 Z = HCOMP(3,M)
120 RL = 0.5D0*(BL + CLSUNL - 4.0D0*TEFFL - C4PIL - CSIGL)
121 GL = CGL + HSTOT - RL - RL
122 PLIM = HP(M)
123C G Somers 10/14, FOR SPOTTED RUNS, FIND THE
124C PRESSURE AT THE AMBIENT TEMPERATURE ATEFFL
125 IF(LC(M).AND.SPOTF.NE.0.0.AND.SPOTX.NE.1.0)THEN
126 ATEFFL = TEFFL - 0.25*LOG10(SPOTF*SPOTX**4.0+1.0-SPOTF)
127 ELSE
128 ATEFFL = TEFFL
129 ENDIF
130 CALL ENVINT(B,FPL,FTL,GL,HSTOT,IXX,LPRT,LSBC0,
131 * * PLIM,RL,ATEFFL,X,Z,DUM1,IDUM,KATM,KENV,KSAHA,
132 * * DUM2,DUM3,DUM4,LPULPT,CMIXL)
133C PPHOT is now set, and structure variables are caluclated if
134C LCALCENV = .TRUE..
135C
136C IF LNEWTCZ IS FALSE, THEN TAUCZ WILL HAVE BEEN SET IN ENVINT, IF THE
137C TOP OF THE INTERIOR MODEL IS RADIATIVE. CHECK IF TAUCZ = 0.0. IF NOT,
138C THEN GO TO THE END.
139C
140 IF (TAUCZ.NE.0.0) GOTO 100
141C
142C COLLECT THE NECESSARY STRUCTURE VARIABLES INTO DUMMY VECTORS.
143 MM = M
144 DO I=1,MM
145 DO J=1,15
146 HCOMPF(J,I) = HCOMP(J,I)
147 ENDDO
148 HRF(I) = HR(I)
149 HPF(I) = HP(I)
150 HDF(I) = HD(I)
151 HSF(I) = HS1(I)
152 HGF(I) = HS1(I)*EXP(CLN*(CGL-2.0D0*HR(I)))
153 HTF(I) = HT(I)
154
155 HVF(I) = SVEL(I)
156 DELF1(I) = SDEL(1,I)
157 DELF2(I) = SDEL(3,I)
158 LCF(I) = LC(I)
159 ENDDO
160C
161 IF(LCALCENV.AND.LNEWTCZ)THEN
162C IF CHKPRS < 1, THEN STITCH THE ENVELOPE ONTO THE INTERIOR.
163C ENVELOPE WAS JUST INTEGRATED IN ENVINT ABOVE, SO USE THAT RUN.
164C THIS CODE BORROWED FROM STITCH.F.
165 MM = M+NUMENV-1
166 DO I=M+1,MM
167 DO J=1,15
168 HCOMPF(J,I) = HCOMP(J,M+1)
169 ENDDO
170 HRF(I) = ENVR(I-M+1)
171 HPF(I) = ENVP(I-M+1)
172 HDF(I) = ENVD(I-M+1)
173 HSF(I) = EXP(CLN*(HSTOT+ENVS(I-M+1)))
174 HGF(I) = HSF(I)*EXP(CLN*(CGL-2.0D0*HRF(I)))
175 HTF(I) = ENVT(I-M+1)
176
177 HVF(I) = EVELS(I-M+1)
178 DELF1(I) = EDELS(1,I-M+1)
179 DELF2(I) = EDELS(2,I-M+1)
180 LCF(I) = LCENV(I-M+1)
181 ENDDO
182 ENDIF
183C CALL TAUINT
184 IF(LNEWTCZ)THEN
185C CALL TAUINTNEW(HCOMPF,HS2,HSF,LCF,HRF,HPF,HDF,HGF,MM,M,HVF,
186C * DELF1,DELF2,HSTOT,RBCZ) ! KC 2025-05-31
187 CALL TAUINTNEW(HSF,LCF,HRF,HPF,HDF,HGF,MM,M,HVF,
188 * * DELF1,DELF2,RBCZ)
189 ELSE
190C CALL TAUINT(HCOMPF,HS2,HSF,LCF,HRF,HPF,HDF,HGF,MM,HVF,
191C * DELF1,DELF2,HSTOT) ! KC 2025-05-31
192 CALL TAUINT(HSF,LCF,HRF,HPF,HDF,HGF,MM,HVF,
193 * * DELF1,DELF2)
194 ENDIF
195C RETURN FULL FUNCTIONALITY TO ENVINT
196 100 100 CONTINUE
197 LCALCENV = .TRUE.
198 RETURN
199 END
1"""Python version of gettau.f (YREC development, 7be4133): the convective
2overturn timescale near the base of the surface convection zone."""
3
4import math
5
6import numpy as np
7
8from pyrec import constants_mod
9from pyrec import dimensions_mod
10from pyrec import envstruct_mod
11from pyrec import nmlpar_mod
12from pyrec import ovrtrn_mod
13from pyrec import scrtch_mod
14from pyrec.envint import envint
15from pyrec.tauint import tauint
16from pyrec.tauintnew import tauintnew
17
18JSON = dimensions_mod.json
19
20# GETTAU has SAVE: its work arrays are module-level.
21hcompf = np.zeros((16, JSON + 1))
22hrf = np.zeros(JSON + 1)
23hpf = np.zeros(JSON + 1)
24hdf = np.zeros(JSON + 1)
25hsf = np.zeros(JSON + 1)
26htf = np.zeros(JSON + 1)
27hgf = np.zeros(JSON + 1)
28hvf = np.zeros(JSON + 1)
29delf1 = np.zeros(JSON + 1)
30delf2 = np.zeros(JSON + 1)
31lcf = np.zeros(JSON + 1, dtype=bool)
32dum1 = np.zeros(5)
33dum2 = np.zeros(4)
34dum3 = np.zeros(4)
35dum4 = np.zeros(4)
36lallcz = False
37
38
39def gettau(hcomp: np.ndarray, hr: np.ndarray, hp: np.ndarray, hd: np.ndarray, hs1: np.ndarray, ht: np.ndarray,
40 fp: np.ndarray, ft: np.ndarray, teffl: float, hstot: float, bl: float, m: int, lc: np.ndarray, rbcz: float,
41 cmixl: float) -> float:
42 """Convective overturn time one pressure scale height above the base of
43 the surface convection zone ("G Somers, 3/17").
44
45 Uses the interior model, the envelope integration, or the two stitched
46 together. Sets ``ovrtrn_mod.taucz`` and ``ovrtrn_mod.pphot``.
47
48 Translates: gettau.f#GETTAU (7be4133)
49
50 Parameters
51 ----------
52 hcomp, hr, hp, hd, hs1, ht, fp, ft, lc : arrays
53 The model (composition, log r, log P, log rho, mass, log T, the
54 form factors, convective flags).
55 teffl, hstot, bl : float
56 log Teff, log total mass, log L.
57 m : int
58 Number of model points.
59 rbcz : float
60 Radius of the convection zone's base (solar radii); set by
61 TAUINTNEW, left unchanged by the old method.
62 cmixl : float
63 Mixing-length parameter, passed on to ENVINT.
64
65 Returns
66 -------
67 rbcz
68
69 """
70
71 global lallcz
72 cln = constants_mod.cln
73 nml = nmlpar_mod
74
75 # Fortran lines 79–80.
76 ovrtrn_mod.taucz = 0.0
77 ovrtrn_mod.pphot = 0.0
78
79 # Base of the surface convection zone, scanning inward (Fortran lines
80 # 88–93).
81 for i in range(m - 1, 0, -1): # label 71
82 if not lc[i]:
83 break # GOTO 81
84 else:
85 lallcz = True # unused, as in the Fortran
86 i = 0
87 imax = i + 1 # label 81
88
89 # Keep the envelope's structure if one scale height above the base may
90 # lie in the envelope (Fortran lines 95–103).
91 # Question (see the page): "at least 3 PSCAS".
92 chkprs = hp[imax] - hp[m]
93 nml.lcalcenv = chkprs < 1.0 or not nml.lnewtcz
94
95 # Integrate the envelope (Fortran lines 107–132).
96 fpl = fp[m]
97 ftl = ft[m]
98 idum = 0
99 b = math.exp(cln * bl)
100 katm = 0
101 kenv = 0
102 ksaha = 0
103 ixx = 0
104 lprt = True
105 lsbc0 = False
106 lpulpt = False
107 x = hcomp[1, m]
108 z = hcomp[3, m]
109 rl = 0.5 * (bl + constants_mod.clsunl - 4.0 * teffl - constants_mod.c4pil
110 - constants_mod.csigl)
111 gl = constants_mod.cgl + hstot - rl - rl
112 plim = hp[m]
113 spotf = nmlpar_mod.spotf
114 spotx = nmlpar_mod.spotx
115 if lc[m] and spotf != 0.0 and spotx != 1.0:
116 ateffl = teffl - 0.25 * math.log10(spotf * spotx ** 4.0 + 1.0 - spotf)
117 else:
118 ateffl = teffl
119 rl, idum, katm, kenv, ksaha = envint(
120 b, fpl, ftl, gl, hstot, ixx, lprt, lsbc0, plim, rl, ateffl, x, z,
121 dum1, idum, katm, kenv, ksaha, dum2, dum3, dum4, lpulpt, cmixl)
122
123 # The old method's TAUCZ, set in ENVINT, ends here (Fortran line 140).
124 if ovrtrn_mod.taucz == 0.0:
125 # The interior, with g = G m / r**2, velocities and gradients from
126 # the last physics pass (Fortran lines 143–159).
127 # Question (see the page): stale interior velocities.
128 mm = m
129 for i in range(1, mm + 1):
130 hcompf[1:16, i] = hcomp[1:16, i]
131 hrf[i] = hr[i]
132 hpf[i] = hp[i]
133 hdf[i] = hd[i]
134 hsf[i] = hs1[i]
135 hgf[i] = hs1[i] * math.exp(cln * (constants_mod.cgl - 2.0 * hr[i]))
136 htf[i] = ht[i]
137 hvf[i] = scrtch_mod.svel[i]
138 delf1[i] = scrtch_mod.sdel[1, i]
139 delf2[i] = scrtch_mod.sdel[3, i]
140 lcf[i] = lc[i]
141
142 # The envelope, points 2 to NUMENV (Fortran lines 161–182).
143 if nml.lcalcenv and nml.lnewtcz:
144 es = envstruct_mod
145 mm = m + es.numenv - 1
146 for i in range(m + 1, mm + 1):
147 k = i - m + 1
148 # HCOMP(J,M+1) is one point past the model; hcompf is read
149 # nowhere (see the page).
150 hcompf[1:16, i] = hcomp[1:16, m + 1]
151 hrf[i] = es.envr[k]
152 hpf[i] = es.envp[k]
153 hdf[i] = es.envd[k]
154 hsf[i] = math.exp(cln * (hstot + es.envs[k]))
155 hgf[i] = hsf[i] * math.exp(cln * (constants_mod.cgl - 2.0 * hrf[i]))
156 htf[i] = es.envt[k]
157 hvf[i] = es.evels[k]
158 delf1[i] = es.edels[1, k]
159 delf2[i] = es.edels[2, k]
160 lcf[i] = es.lcenv[k]
161
162 # The new or the old method (Fortran lines 184–194).
163 if nml.lnewtcz:
164 rbcz = tauintnew(hsf, lcf, hrf, hpf, hdf, hgf, mm, m, hvf,
165 delf1, delf2, rbcz)
166 else:
167 tauint(hsf, lcf, hrf, hpf, hdf, hgf, mm, hvf, delf1, delf2)
168
169 # Fortran lines 196–197 (label 100).
170 nml.lcalcenv = True
171 return rbcz