1C
2C
3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
4C OVERSH
5CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
6 SUBROUTINE OVERSH(HCOMP,HD,HP,HR,HS,HT,M,MXZONE,MXZON0,NZONE)
7C 10/15/26 MHP via Claude
8C code changed to take JSON from DIMENSIONS_MOD instead of declaring
9C PARAMETER(JSON=5000) here.
10 USE DIMENSIONS_MOD
11C 10/14/26 MHP via Claude
12C code changed to convert COMMON/DPMIX/ into DPMIX_MOD.
13 USE DPMIX_MOD
14C 10/14/26 MHP via Claude
15C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
16 USE NMLPAR_MOD
17C 10/14/26 MHP via Claude
18C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
19 USE CONSTANTS_MOD
20C 10/14/26 MHP via Claude
21C code changed to convert COMMON/IOUNITS/ into IOUNITS_MOD.
22 USE IOUNITS_MOD
23C 10/20/26 MHP via Claude
24C code changed to replace implicit typing with IMPLICIT NONE and
25C explicit declarations.
26 IMPLICIT NONE
27 REAL*8 HCOMP,HD,HP,HR,HS,HT,PSCALD,PSCALU,R,RCZ,ROS
28 INTEGER I,ID,J,JEDGE,M,MXZON0,MXZONE,NZONE
29 LOGICAL*4 LFLAGD,LFLAGU
30
31C THIS SR COMPUTES THE LOCAL PRESSURE SCALE HEIGHT AT BOTH EDGES OF A
32C GIVEN CONVECTIVE REGION AND LOCATES THE BOUNDARIES OF OVERSHOOT
33C REGIONS BASED ON THE USER-SPECIFIED EXTENT.
34
35
36C 9/25/26 MHP via Claude
37C code changed to consolidate all I/O logical unit numbers, previously
38C scattered across COMMON/LUOUT/, COMMON/LUNUM/, COMMON/ALEX06/,
39C COMMON/ACDPTH/, COMMON/NEWOPAC/, COMMON/LOPAL95/, COMMON/ATMOS2/,
40C COMMON/ALATM03/, COMMON/OPALEOS/, and COMMON/SCV2/, into a single
41C COMMON/IOUNITS/
42C 9/25/26 MHP via Claude
43C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
44C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
45C 10/12/26 MHP via Claude
46C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
47C namelist variables that the physics routines read from 27 COMMON
48C blocks which also held derived or working members. Those blocks keep
49C only their non-namelist members; five of them -- NEWMX, VMULT,
50C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
51C Derivation-only namelist variables from the same blocks went to
52C COMMON/NMLBYPASS/ instead, not here.
53C
54C Declared identically in all 121 files that hold any of these members.
55C Generated from one member list, so every copy is byte-identical; the
56C linker's 'size of symbol changed' warning is the check that they are.
57 DIMENSION HCOMP(15,JSON),HD(JSON),HP(JSON),HR(JSON),HS(JSON),
58 * * HT(JSON),MXZONE(12,2),MXZON0(12,2)
59 SAVE
60
61 IOV1 = -1
62 IOV2 = -1
63 DO 100 I = 1,NZONE
64C DETERMINE IF THIS REGION IS A CORE CONVECTION ZONE, SURFACE CZ,
65C OR INTERMEDIATE CZ. THERE ARE SEPARATE FLAGS GOVERNING WHETHER
66C OVERSHOOT WILL BE PERFORMED IN EACH CASE, AND SEPARATE USER
67C PARAMETERS GOVERNING THE DEGREE OF OVERSHOOT.
68 IF(MXZONE(I,1).EQ.1)THEN
69C CONVECTIVE CORE
70C CHECK FOR A FULLY CONVECTIVE STAR; SKIP THIS SR IF THERE IS ONE.
71 IF(MXZONE(I,2).EQ.M)THEN
72 WRITE(ISHORT,5)
73 5 5 FORMAT(1X,'FULLY CONVECTIVE MODEL - NO OVERSHOOT')
74 WRITE(ISHORT,200)(MXZON0(1,J),J= 1,2)
75 RETURN
76 ENDIF
77C SKIP IF NO CORE OVERSHOOT IS DESIRED.
78 IF(.NOT.LOVSTC)GOTO 100
79 LFLAGU = .TRUE.
80 LFLAGD = .FALSE.
81 JEDGE = MXZONE(I,2)
82 CALL HSUBP (HCOMP,HD,HP,HR,HS,HT,JEDGE,PSCALU)
83C PSCALU IS THE PRESSURE SCALE HEIGHT ABOVE THE CONVECTIVE REGION;
84C ALPHAC IS THE DESIRED OVERSHOOT (IN SCALE HEIGHTS).
85C PSCALU = PSCALU*ALPHAC
86C JVS 07/13 ALLOW FOR THE LIMITING OF OVERSHOOTING ABOVE THE CONVECTIVE
87C CORES OF LOVE MASS STARS AS PER WOO & DEMARQUE 2001
88 IF (LOVMAX) THEN
89 PSCALU = MIN(PSCALU*ALPHAC, BETAC*EXP(CLN*HR(JEDGE)))
90 ELSE
91 PSCALU = PSCALU*ALPHAC
92 ENDIF
93
94 ELSE IF(MXZONE(I,2).EQ.M)THEN
95C CONVECTIVE ENVELOPE
96C SKIP IF NO ENVELOPE OVERSHOOT IS DESIRED.
97 IF(.NOT.LOVSTE)GOTO 100
98 LFLAGU = .FALSE.
99 LFLAGD = .TRUE.
100 JEDGE = MXZONE(I,1)
101 CALL HSUBP (HCOMP,HD,HP,HR,HS,HT,JEDGE,PSCALD)
102C PSCALD IS THE PRESSURE SCALE HEIGHT BELOW THE CONVECTIVE REGION;
103C ALPHAE IS THE DESIRED OVERSHOOT (IN SCALE HEIGHTS).
104 PSCALD = PSCALD*ALPHAE
105 ELSE
106C INTERMEDIATE CONVECTION ZONE (NOT INCLUDING CENTRAL OR SURFACE POINT).
107C SKIP IF NO INTERMEDIATE CONVECTION.
108 IF(.NOT.LOVSTM)GOTO 100
109 LFLAGU = .TRUE.
110 LFLAGD = .TRUE.
111C PSCALU AND PSCALD HAVE THE SAME MEANING AS ABOVE; OVERSHOOT BOTH BELOW
112C AND ABOVE IS PERFORMED BY AN AMOUNT ALPHAM.
113 JEDGE = MXZONE(I,1)
114 CALL HSUBP (HCOMP,HD,HP,HR,HS,HT,JEDGE,PSCALD)
115 PSCALD = PSCALD*ALPHAM
116 JEDGE = MXZONE(I,2)
117 CALL HSUBP (HCOMP,HD,HP,HR,HS,HT,JEDGE,PSCALU)
118 PSCALU = PSCALU*ALPHAM
119 ENDIF
120C COMPUTE EXTENSION OF CONVECTION ZONE BELOW SCHWARTZSCHILD BOUNDARY.
121 IF(LFLAGD)THEN
122 ID = MXZONE(I,1)
123 RCZ = EXP(CLN*HR(ID))
124 ROS = RCZ - PSCALD
125C THE OVERSHOOT REGION IS EXTENDED THE RADIAL DISTANCE PSCALD DOWN; THE
126C LAST POINT LESS THAN PSCALD FROM THE FORMAL EDGE OF THE CZ IS DEFINED
127C AS THE NEW EDGE OF THE MIXED REGION.
128 DO 10 J = ID-1,1,-1
129 R = EXP(CLN*HR(J))
130 IF(R.LT.ROS)GOTO 20
131 10 10 CONTINUE
132C IF THE CODE GETS HERE, THE OVERSHOOT REGION EXTENDS BELOW THE FIRST POINT.
133C THE CODE WILL ASSIGN THE FIRST POINT AS THE LOWER EDGE(I.E. THE CZ WILL
134C EXTEND TO THE CENTER).
135 J = 0
136 20 20 CONTINUE
137C FOR ROTATING MODELS, ENSURE THAT THERE IS AT LEAST ONE RADIATIVE POINT
138C IN THE OVERSHOOT REGION.
139 MXZONE(I,1) = J + 1
140C 11/91 MHP CHANGED TO REQUIRE AN OVERSHOOT ZONE ONLY IF LINSTB=T.
141 IF(LROT .AND. LINSTB .AND. MXZONE(I,1).EQ.MXZON0(I,1))
142 * * MXZONE(I,1) = MXZONE(I,1)-1
143C DBG 8/94 STORE POSITION OF OVERSHOOT FOR ADIABATIC EXTENSION
144 IOV2 = ID
145 IOV1 = MXZONE(I,1)
146 ENDIF
147C COMPUTE EXTENSION OF CONVECTION ZONE ABOVE SCHWARTZSCHILD BOUNDARY.
148 IF(LFLAGU)THEN
149 ID = MXZONE(I,2)
150 RCZ = EXP(CLN*HR(ID))
151 ROS = RCZ + PSCALU
152C THE OVERSHOOT REGION IS EXTENDED THE RADIAL DISTANCE PSCALU UP; THE
153C LAST POINT LESS THAN PSCALU FROM THE FORMAL EDGE OF THE CZ IS DEFINED
154C AS THE NEW EDGE OF THE MIXED REGION.
155 DO 30 J = ID+1,M
156 R = EXP(CLN*HR(J))
157 IF(R.GT.ROS)GOTO 40
158 30 30 CONTINUE
159C IF THE CODE GETS HERE, THE OVERSHOOT REGION EXTENDS ABOVE THE LAST POINT.
160C THE CODE WILL ASSIGN THE LAST POINT AS THE UPPER EDGE(I.E. THE CZ WILL
161C EXTEND TO THE SURFACE).
162 J = M + 1
163 40 40 CONTINUE
164 MXZONE(I,2) = J - 1
165C 11/91 MHP CHANGED TO REQUIRE AN OVERSHOOT ZONE ONLY IF LINSTB=T.
166 IF(LROT .AND. LINSTB .AND. MXZONE(I,2).EQ.MXZON0(I,2))
167 * * MXZONE(I,2) = MXZONE(I,2)+1
168 ENDIF
169 100 100 CONTINUE
170C OUTPUT : THE OLD AND NEW MIXED REGIONS ARE PRINTED OUT IN ISHORT.
171 WRITE(ISHORT,200)((MXZON0(I,J),J= 1,2),I=1,NZONE)
172 200 200 FORMAT(1X,'MIXED REGIONS WITHOUT OVERSHOOT',
173 * * 4('[',I4,'-',I4,' ]'))
174 WRITE(ISHORT,210)((MXZONE(I,J),J= 1,2),I=1,NZONE)
175 210 210 FORMAT(1X,'MIXED REGIONS WITH OVERSHOOT ',
176 * * 4('[',I4,'-',I4,' ]'))
177
178 RETURN
179 END1"""Python version of oversh.f (YREC 7be4133): convective overshoot at the
2edges of each convection zone."""
3
4import math
5import numpy as np
6
7from pyrec import constants_mod
8from pyrec import dpmix_mod
9from pyrec import iounits_mod
10from pyrec import nmlpar_mod
11from pyrec.hsubp import hsubp
12
13
14def _zone_lines(label: str, mx: np.ndarray, nzone: int) -> str:
15 """FORMAT(1X,label,4('[',I4,'-',I4,' ]')): four zones a line; further
16 lines restart at the repeated group, without the label (Fortran's
17 format reversion; Fortran lines 170–176)."""
18
19 groups = [f"[{mx[i, 1]:4d}-{mx[i, 2]:4d} ]" for i in range(1, nzone + 1)]
20 lines = [" " + label + "".join(groups[:4])]
21 for n in range(4, len(groups), 4):
22 lines.append("".join(groups[n:n + 4]))
23 return "\n".join(lines)
24
25
26def oversh(hcomp: np.ndarray, hd: np.ndarray, hp: np.ndarray, hr: np.ndarray, hs: np.ndarray, ht: np.ndarray, m: int,
27 mxzone: np.ndarray, mxzon0: np.ndarray, nzone: int) -> None:
28 """Extend each convection zone by overshoot: by alpha_c H_P above a
29 core (with LOVMAX, at most beta_c r), alpha_e H_P below the envelope,
30 alpha_m H_P both ways for an intermediate zone. H_P is the pressure
31 scale height at the zone's formal edge (HSUBP). Also sets IOV1, IOV2
32 in DPMIX_MOD for the last zone overshooting downward.
33
34 Translates: oversh.f#OVERSH (7be4133)
35
36 Arguments: the model hcomp, hd, hp, hr, hs, ht (index 0 unused); m, the
37 number of shells; mxzone[12+1, 2+1], the zones' edges, changed in place;
38 mxzon0, the edges without overshoot; nzone. Returns nothing.
39
40 """
41
42 nml = nmlpar_mod
43 cln = constants_mod.cln
44 ishort = iounits_mod.ishort
45 pscalu = 0.0
46 pscald = 0.0
47
48 # Fortran lines 61–62.
49 # Question (see the page): IOV1, IOV2 keep only the last zone.
50 dpmix_mod.iov1 = -1
51 dpmix_mod.iov2 = -1
52
53 for i in range(1, nzone + 1):
54 # The zone's type and the overshoot distances (Fortran lines 64–119).
55 if mxzone[i, 1] == 1:
56 if mxzone[i, 2] == m:
57 iounits_mod.write(ishort,
58 " FULLY CONVECTIVE MODEL - NO OVERSHOOT")
59 # Never reached: CONVEC returns before calling OVERSH for a
60 # fully convective star (see the page).
61 iounits_mod.write(ishort, _zone_lines(
62 "MIXED REGIONS WITHOUT OVERSHOOT", mxzon0, 1))
63 return
64 if not nml.lovstc:
65 continue
66 lflagu = True
67 lflagd = False
68 jedge = mxzone[i, 2]
69 pscalu = hsubp(hcomp, hd, hp, hr, hs, ht, jedge, pscalu)
70 if nml.lovmax:
71 pscalu = min(pscalu * nml.alphac,
72 nml.betac * math.exp(cln * hr[jedge]))
73 else:
74 pscalu = pscalu * nml.alphac
75 elif mxzone[i, 2] == m:
76 if not nml.lovste:
77 continue
78 lflagu = False
79 lflagd = True
80 jedge = mxzone[i, 1]
81 pscald = hsubp(hcomp, hd, hp, hr, hs, ht, jedge, pscald)
82 pscald = pscald * nml.alphae
83 else:
84 if not nml.lovstm:
85 continue
86 lflagu = True
87 lflagd = True
88 jedge = mxzone[i, 1]
89 pscald = hsubp(hcomp, hd, hp, hr, hs, ht, jedge, pscald)
90 pscald = pscald * nml.alpham
91 jedge = mxzone[i, 2]
92 pscalu = hsubp(hcomp, hd, hp, hr, hs, ht, jedge, pscalu)
93 pscalu = pscalu * nml.alpham
94
95 # Downward: the innermost point with r >= r_edge - d (Fortran lines
96 # 120–146).
97 if lflagd:
98 id_ = mxzone[i, 1]
99 rcz = math.exp(cln * hr[id_])
100 ros = rcz - pscald
101 for j in range(id_ - 1, 0, -1):
102 r = math.exp(cln * hr[j])
103 if r < ros:
104 break # goto 20
105 else:
106 j = 0
107 # label 20
108 mxzone[i, 1] = j + 1
109 if nml.lrot and nml.linstb and mxzone[i, 1] == mxzon0[i, 1]:
110 mxzone[i, 1] = mxzone[i, 1] - 1
111 dpmix_mod.iov2 = id_
112 dpmix_mod.iov1 = mxzone[i, 1]
113
114 # Upward: the outermost point with r <= r_edge + d (Fortran lines
115 # 147–168).
116 if lflagu:
117 id_ = mxzone[i, 2]
118 rcz = math.exp(cln * hr[id_])
119 ros = rcz + pscalu
120 for j in range(id_ + 1, m + 1):
121 r = math.exp(cln * hr[j])
122 if r > ros:
123 break # goto 40
124 else:
125 j = m + 1
126 # label 40
127 mxzone[i, 2] = j - 1
128 if nml.lrot and nml.linstb and mxzone[i, 2] == mxzon0[i, 2]:
129 mxzone[i, 2] = mxzone[i, 2] + 1
130
131 # label 100 ends the loop. The zones without and with overshoot
132 # (Fortran lines 170–176).
133 iounits_mod.write(ishort, _zone_lines(
134 "MIXED REGIONS WITHOUT OVERSHOOT", mxzon0, nzone))
135 iounits_mod.write(ishort, _zone_lines(
136 "MIXED REGIONS WITH OVERSHOOT ", mxzone, nzone))