1C $$$$$$
2 SUBROUTINE SETUP_GRSETT(DT,HQPR,HR,HD,HS1,HT,LC,M,STOT,COD1,COD2,
3 * * HCOMP,HRU,HTU,IBEGIN,IEND,LALLCZ,QCOD1X,QCOD2X,COD1Z,COD2Z,QCOD1Z,QCOD2Z)
4C 10/15/26 MHP via Claude
5C code changed to take JSON from DIMENSIONS_MOD instead of declaring
6C PARAMETER(JSON=5000) here.
7 USE DIMENSIONS_MOD
8C 10/14/26 MHP via Claude
9C code changed to convert COMMON/SCRTCH/ into SCRTCH_MOD.
10 USE SCRTCH_MOD
11C 10/14/26 MHP via Claude
12C code changed to convert COMMON/CONFAC/ into CONFAC_MOD.
13 USE CONFAC_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 AH,AP,AT,ATOMWT,COD1,COD1Z,COD2,COD2Z,CRSUN_BAH,CSECYR_BAH,
28 * * DT,FAC,FAC2,HCOMP,HD,HQPR,HR,HRU,HS1,HT,HTU,QACX,QAPX,QATX,
29 * * QCOD1X,QCOD1Z,QCOD2X,QCOD2Z,RHO,STOT,T,TAC,TAP,TAT,TCL,X,
30 * * X2,X3,XFRAC,XZ,Z,ZSPEC,ZZ
31 INTEGER I,IBEGIN,IEND,II,JJ,M,NSPEC
32 LOGICAL*4 LALLCZ,LC
33
34C 10/13/26 MHP via Claude
35C formerly COMMON/GRAVSZ/, now dummy arguments.
36 DIMENSION COD1Z(JSON),COD2Z(JSON),QCOD1Z(JSON),QCOD2Z(JSON)
37
38C 9/25/26 MHP via Claude
39C code changed to consolidate all I/O logical unit numbers, previously
40C scattered across COMMON/LUOUT/, COMMON/LUNUM/, COMMON/ALEX06/,
41C COMMON/ACDPTH/, COMMON/NEWOPAC/, COMMON/LOPAL95/, COMMON/ATMOS2/,
42C COMMON/ALATM03/, COMMON/OPALEOS/, and COMMON/SCV2/, into a single
43C COMMON/IOUNITS/
44C 9/25/26 MHP via Claude
45C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
46C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
47C 9/24/26 MHP via Claude
48C code changed to remove dead CMIXL from COMMON/CONST3/; it is now
49C passed as an explicit argument where actually used
50C 10/12/26 MHP via Claude
51C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
52C namelist variables that the physics routines read from 27 COMMON
53C blocks which also held derived or working members. Those blocks keep
54C only their non-namelist members; five of them -- NEWMX, VMULT,
55C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
56C Derivation-only namelist variables from the same blocks went to
57C COMMON/NMLBYPASS/ instead, not here.
58C
59C Declared identically in all 121 files that hold any of these members.
60C Generated from one member list, so every copy is byte-identical; the
61C linker's 'size of symbol changed' warning is the check that they are.
62C MHP 3/94 ADDED METAL DIFFUSION
63C 10/13/26 MHP via Claude
64C code changed to replace COMMON/GRAVSZ/ with explicit arguments:
65C setup_grsett.f fills these four and model_to_equal.f reads them, and
66C grsett.f calls both, so grsett.f now owns the storage.
67C MHP 8/94 ADDED I/O FOR DIFFUSION
68C 10/13/26 MHP via Claude
69C code changed to remove COMMON/GSCOF/: none of its four members is
70C referenced in executable code anywhere.
71C COMMON/GSCOF2/TAPP(JSON),TATP(JSON),TCLP(JSON),TAPZP(JSON),
72C * TATZP(JSON)
73CFD 10/09 ADDED COMMON BLOCK FOR EXTRA MIXING. IT MIMIC SOME MIXING BY AFFECTING
74C THE SETTLING COEFFICIENT DIRECTLY (in setup_grsett.f)
75C
76 DIMENSION HQPR(JSON),HR(JSON),HS1(JSON),HT(JSON),LC(JSON),
77 * * HRU(JSON),HTU(JSON),COD1(JSON),COD2(JSON),QCOD1X(JSON),
78 * * QCOD2X(JSON),HCOMP(15,JSON),HD(JSON)
79C MHP 8/94 ADDED ATOMIC WEIGHTS AND CHARGES FOR H,HE,FE,ELECTRONS -
80C NEEDED FOR FULL THOUL COEFFICIENTS
81 DIMENSION ATOMWT(4),ZSPEC(4),TAP(4),TAT(4),TAC(4,4),
82 * * TCL(4,4),XFRAC(4)
83c additional variables to be declared for variable ln lambda
84c intermediate variables:
85 REAL*8 ZXA,AC,NI,CZ,XIJ,NE,AO,LAMBDAD,LAMBDA,C(4)
86 REAL*8 LN_LAMBDA
87 DATA ATOMWT/1.008D0,4.004D0,55.86D0,5.486D-4/
88 DATA ZSPEC/1.0D0,2.0D0,26.0D0,-1.0D0/
89 DATA NSPEC/4/
90 SAVE
91
92
93C OUTPUT VARIABLES :
94C
95C HRU - VECTOR OF UNLOGGED RADII IN BAHCALL AND LOEB UNITS.
96C HTU - VECTOR OF UNLOGGED TEMPERATURES IN BAHCALL AND LOEB UNITS.
97C IBEGIN - FIRST ZONE FOR DIFFUSION PURPOSES (EITHER THE FIRST MODEL POINT
98C OR THE OUTERMOST POINT OF A CENTRAL CONVECTION ZONE).
99C IEND - LAST ZONE FOR DIFFUSION PURPOSES (EITHER THE LAST MODEL POINT OR
100C THE INNERMOST POINT OF A SURFACE CONVECTION ZONE).
101C THE VECTORS HQPR AND HS1, AND THE SCALARS DT AND STOT, ARE ALSO CONVERTED
102C TO BAHCALL AND LOEB UNITS.
103C CONSTANTS DEFINED :
104C CLN = CONVERSION FACTOR FROM LN TO LOG10
105C CRSUN_BAH = SOLAR RADIUS (CM)
106C CSECYR_BAH = NUMBER OF SECONDS IN A YEAR.
107 CRSUN_BAH=6.9598D10
108 CSECYR_BAH=3.1558D7
109C LALLCZ=T FOR FULLY CONVECTIVE MODEL(AND IF TRUE, DIFFUSION IS SKIPPED).
110 LALLCZ=.FALSE.
111C CHECK FOR CONVECTIVE CORE.
112 IF(LC(1))THEN
113 DO 10 I=2,M
114 IF(.NOT.LC(I))GOTO 20
115 10 10 CONTINUE
116C DIFFUSION NOT COMPUTED FOR FULLY CONVECTIVE MODELS.
117 LALLCZ=.TRUE.
118 WRITE(ISHORT,15)
119 15 15 FORMAT(1X,' FULLY CONVECTIVE MODEL - NO SETTLING')
120 GOTO 9999
121 20 20 CONTINUE
122C COMPUTE OVERSHOOT (TO BE ADDED).
123 IBEGIN = I-1
124 ELSE
125 IBEGIN = 1
126 ENDIF
127C MHP 6/90 CHECK FOR HYDROGEN-EXHAUSTED CORE.
128 DO 23 I = IBEGIN,M
129 IF(HCOMP(1,I).GT.XMIN)GOTO 25
130 23 23 CONTINUE
131C HYDROGEN-FREE MODEL - EXIT.
132 WRITE(ISHORT,16)XMIN
133 16 16 FORMAT(1X,'X BELOW ',F9.6,' IN WHOLE MODEL-NO SETTLING')
134 LALLCZ = .TRUE.
135 GOTO 9999
136 25 25 CONTINUE
137 IBEGIN = I
138C CHECK FOR CONVECTIVE ENVELOPE.
139 IF(LC(M))THEN
140 DO 30 I=M-1,2,-1
141 IF(.NOT.LC(I))GOTO 40
142 30 30 CONTINUE
143 40 40 CONTINUE
144C COMPUTE OVERSHOOT (TO BE ADDED).
145 IEND = I+1
146 ELSE
147 IEND = M
148 ENDIF
149C CHECK FOR HELIUM-EXHAUSTED SURFACE.
150C OUTER POINT IS SET WHEREVER Y>YMIN.
151 DO 45 I=IEND,1,-1
152 IF(HCOMP(2,I).GT.YMIN) GOTO 47
153 45 45 CONTINUE
154C HYDROGEN-FREE MODEL - EXIT.
155 WRITE(ISHORT,17)YMIN
156 17 17 FORMAT(1X,'Y BELOW ',F9.6,' IN WHOLE MODEL-NO SETTLING')
157 LALLCZ = .TRUE.
158 GOTO 9999
159 47 47 CONTINUE
160 IEND = I
161C CON_MASS=CONVERSION FACTOR FOR MASS.
162C CON_RADIUS=CONVERSION FACTOR FOR RADIUS.
163C CON_TEMP=CONVERSION FACOTR FOR TEMPERATURE.
164C CON_TIME=CONVERSION FACTOR FOR TIME.
165 CON_RAD=1.0D0/CRSUN_BAH
166 CON_MASS=1.0D-2*CON_RAD**3
167 CON_TEMP=1.0D-7
168C INCLUDES FACTOR OF 2.2 FROM LN LAMBDA
169 CON_TIME=2.7D13*CSECYR_BAH
170C CONVERT LOG(RADIUS) AND LOG(TEMPERATURE) TO NATURAL UNITS.
171C ALSO CONVERT NATURAL UNITS TO BAHCALL AND LOEB UNITS.
172 DO 50 I=1,M
173
174 HRU(I)=EXP(CLN*HR(I))*CON_RAD
175 HTU(I)=EXP(CLN*HT(I))*CON_TEMP
176 HS1(I)=HS1(I)*CON_MASS
177 HQPR(I)=HQPR(I)/CON_RAD
178C SDEL(2,I)=0.4D0 !COMMENT OUT IN REAL CODE
179 50 50 CONTINUE
180 DT=DT/CON_TIME
181 STOT=STOT*CON_MASS
182C SET UP DIFFUSION COEFFICIENTS.
183C MODIFIED BY BC MAY/90 -- VALID FOR ALL X WITH VARIABLE LN LAMBDA
184C GENERAL EQUATION IS
185C DX/DT = (D/DR(D1)+D/DR(D2 DX/DR))/(RHO*R**2), WHERE
186C D1 = R**2/LN LAMBDA * X * T**5/2 * (DLNP/DR) * (1-X) *
187C [5/4 + DEL*6*(X-0.32)/(5.4+6.3X-4.5X**2)]
188C D2 = R**2/LN LAMBDA * T**5/2 * (X+3)/(X+1)/(3+5X)
189 DO 60 I = 1,M
190
191 X = HCOMP(1,I)
192C MHP 10/02 INITIALIZED X - WAS NOT DONE PRIOR TO USAGE IN SHELL 1
193 IF(ILAMBDA.EQ.2)THEN
194C Noerdlinger's formula (1977 A&A 57,407) for LN LAMBDA:
195C Ln Lambda = -19.7 - ln[4/(3*X + 1)]/2 - ln(rho)/2 + 1.5*ln(T)
196 LN_LAMBDA=-1.97D1 - 0.5D0*LOG(1.0D0/(0.75D0*X+0.25D0))
197 * * -0.5D0*HD(I)*CLN + 1.5D0*HT(I)*CLN
198 ELSE IF(ILAMBDA.EQ.3)THEN
199C Loeb's formula (1989 Phys. Rev. D 39, 1009) for LN LAMBDA
200C ln lambda = -19.105747 - ln(rho)/2 + 1.5*ln(T)
201 LN_LAMBDA=-1.9105747D1-0.50D0*HD(I)*CLN+1.5D0*HT(I)*CLN
202 ELSE
203 LN_LAMBDA = 2.2D0
204 END IF
205C
206 FAC=FGRY*HRU(I)**2*HTU(I)**2.5D0/LN_LAMBDA
207C X = HCOMP(1,I)
208 Z = HCOMP(3,I) + HCOMP(4,I)
209 ZZ = HCOMP(3,I)
210 X2 = X*X
211 IF(.NOT.LTHOUL)THEN
212 XZ = X*Z
213 X3 = X2*X
214 FAC2=5.4D0+6.3D0*X-4.5D0*X2
215 COD1(I)=FAC*HQPR(I)*(X - X2 - XZ)*(1.25D0+
216 * * SDEL(2,I)*6.0D0*(X+0.32D0)/FAC2)
217 COD2(I)=FAC*(X+3.0D0)/(5.0D0*X2 + 8.0D0*X + 3.0D0)
218 QCOD1X(I)=FAC*HQPR(I)*( (1.0D0-2.0D0*X-Z)*(1.25D0+
219 * * (6.0D0*SDEL(2,I)*(X+0.32D0))/FAC2)+(X-X2-XZ)*6.0D0*
220 * * SDEL(2,I)*(3.384D0+2.88D0*X+4.5D0*X2)/FAC2**2 )
221 QCOD2X(I)=-FAC*(5.0D0*X2 + 3.0D1*X + 2.1D1)/
222 * * (5.0D0*X2 + 8.0D0*X + 3.0D0)**2
223 ELSE
224 XFRAC(1) = HCOMP(1,I)
225 XFRAC(2) = HCOMP(2,I)
226 XFRAC(3) = HCOMP(3,I)
227 IF(.NOT.LTHOULFIT)THEN
228 IF(ILAMBDA.EQ.4)THEN
229 RHO = EXP(CLN*HD(I))
230 T = EXP(CLN*HT(I))
231c calculate concentrations from mass fractions:
232 ZXA=0.D0
233 DO II=1,NSPEC-1
234 ZXA=ZXA+ZSPEC(II)*XFRAC(II)/ATOMWT(II)
235 ENDDO
236 DO II=1,NSPEC-1
237 C(II)=XFRAC(II)/(ATOMWT(II)*ZXA)
238 ENDDO
239 C(NSPEC)=1.D0
240c calculate density of electrons (NE) from mass density (RHO):
241 AC=0.D0
242 DO II=1,NSPEC
243 AC=AC+ATOMWT(II)*C(II)
244 ENDDO
245 NE=RHO/(1.6726D-24*AC)
246c calculate interionic distance (AO):
247 NI=0.D0
248 DO II=1,NSPEC-1
249 NI=NI+C(II)*NE
250 ENDDO
251 AO=(0.23873D0/NI)**CC13
252c calculate Debye length (LAMBDAD):
253 CZ=0.D0
254 DO II=1,NSPEC
255 CZ=CZ+C(II)*ZSPEC(II)**2
256 ENDDO
257 LAMBDAD=6.9010D0*SQRT(T/(NE*CZ))
258c calculate LAMBDA to use in Coulomb logarithm:
259 LAMBDA=MAX(LAMBDAD,AO)
260c calculate Coulomb logarithms:
261 DO II=1,NSPEC
262 DO JJ=1,NSPEC
263 XIJ=2.3939D3*T*LAMBDA/ABS(ZSPEC(II)*ZSPEC(JJ))
264 TCL(II,JJ)=0.81245D0
265 * * *LOG(1.D0+0.18769D0*XIJ**1.2D0)
266 ENDDO
267 ENDDO
268 ELSE
269 DO II = 1,NSPEC
270 DO JJ = 1,NSPEC
271 TCL(II,JJ) = LN_LAMBDA
272 END DO
273 END DO
274 ENDIF
275 CALL THDIFF(NSPEC,ATOMWT,ZSPEC,XFRAC,TCL,TAP,TAT,TAC)
276 AP = -TAP(1)
277 AT = -SDEL(2,I)*TAT(1)
278 ELSE
279 AP = 1.58D0 - 2.42D0*X + 0.844D0*X2
280 AT = SDEL(2,I)*(1.90D0 - 2.69D0*X + 0.805D0*X2)
281 ENDIF
282 AC = 1.15D0 - 1.42D0*X + 0.647D0*X2
283 QAPX = -2.42D0 + 1.688D0*X
284 QATX = SDEL(2,I)*(-2.69D0 + 1.61D0*X)
285 QACX = -1.42D0 + 1.294D0*X
286CFD 10/09 Mimic Mixing to reduce settling.
287C COD1(I) = FAC*HQPR(I)*X*(AP+AT)
288 COD1(I) = CSTMIXING*FAC*HQPR(I)*X*(AP+AT)
289 COD2(I) = CSTMIXING*FAC*AC
290 QCOD1X(I) = FAC*HQPR(I)*(AP+AT+X*(QAPX+QATX))
291 QCOD2X(I) = FAC*QACX
292 ENDIF
293C METAL DIFFUSION, USING THE THOUL ET AL. COEFFICIENTS FOR FULLY
294C IONIZED IRON.
295 IF(LDIFZ)THEN
296
297 FAC=FGRZ*HRU(I)**2*HTU(I)**2.5D0/LN_LAMBDA
298 IF(LTHOUL)THEN
299 IF(LTHOULFIT)THEN
300 AP = -0.157D0 -0.511D0*X + 0.389D0*X2
301 AT = SDEL(2,I)*(-1.36D0 - 1.42D0*X + 0.549D0*X2)
302 ELSE
303 AP = -TAP(3)
304 AT = -SDEL(2,I)*TAT(3)
305 ENDIF
306 AH = -0.0375D0 -0.193D0*X + 0.107D0*X2
307CFD 10/09 Mimic Mixing to reduce settling (cstmixing)
308C and add the uncertainties of differential mixing (cstdiffmix).
309C
310C old ver COD1Z(I) = FAC*HQPR(I)*ZZ*(AP+AT)
311 COD1Z(I) = CSTDIFFMIX*CSTMIXING*FAC*HQPR(I)*ZZ*(AP+AT)
312C POSITIVE DIFFUSION COEFFICIENTS NEEDED!
313C old ver. COD2Z(I) = ABS(FAC*AH)
314C old ver. QCOD1Z(I) = FAC*HQPR(I)*(AP+AT)
315 COD2Z(I) = CSTMIXING*ABS(FAC*AH)
316 QCOD1Z(I) = CSTMIXING*FAC*HQPR(I)*(AP+AT)
317 QCOD2Z(I) = 0.0D0
318 ENDIF
319 ENDIF
320C
321C If using Noerdlinger's formula for LN LAMBDA, have a new term
322C in D(D1)/DX
323 IF(ILAMBDA.EQ.2) THEN
324 QCOD1X(I)=QCOD1X(I) + COD1(I)*1.5D0/
325 * * (LN_LAMBDA*(3.0D0*X+1.0D0))
326 END IF
327 60 60 CONTINUE
328 9999 9999 CONTINUE
329 RETURN
330 END
1"""Python version of setup_grsett.f (YREC 7be4133): the range, units and
2diffusion coefficients for the Bahcall-Loeb settling solver (GRSETT)."""
3
4import math
5
6import numpy as np
7
8from pyrec import confac_mod
9from pyrec import constants_mod
10from pyrec import iounits_mod
11from pyrec import nmlpar_mod
12from pyrec import scrtch_mod
13from pyrec.thdiff import thdiff
14
15# Atomic weights and charges of H, He, Fe and electrons (DATA), for the full
16# Thoul et al. coefficients (MHP 8/94).
17NSPEC = 4
18ATOMWT = np.array([0.0, 1.008, 4.004, 55.86, 5.486e-4])
19ZSPEC = np.array([0.0, 1.0, 2.0, 26.0, -1.0])
20
21# Locals kept between calls (SAVE).
22tap = np.zeros(NSPEC + 1)
23tat = np.zeros(NSPEC + 1)
24tac = np.zeros((NSPEC + 1, NSPEC + 1))
25tcl = np.zeros((NSPEC + 1, NSPEC + 1))
26xfrac = np.zeros(NSPEC + 1)
27cfrac = np.zeros(NSPEC + 1) # C(4) in the Fortran: concentrations
28
29
30def setup_grsett(dt: float, hqpr: np.ndarray, hr: np.ndarray, hd: np.ndarray, hs1: np.ndarray, ht: np.ndarray,
31 lc: np.ndarray, m: int, stot: float, cod1: np.ndarray, cod2: np.ndarray, hcomp: np.ndarray,
32 hru: np.ndarray, htu: np.ndarray, ibegin: int, iend: int, lallcz: bool, qcod1x: np.ndarray,
33 qcod2x: np.ndarray, cod1z: np.ndarray, cod2z: np.ndarray, qcod1z: np.ndarray,
34 qcod2z: np.ndarray) -> tuple[float, float, int, int, bool]:
35 """Find the shells where settling is computed (above a convective
36 core with X > XMIN, below a convective envelope), convert the model to
37 Bahcall and Loeb's units (conversion factors to confac_mod), and
38 compute the helium (and, with LDIFZ, metal) diffusion coefficients and
39 their X-derivatives for every shell.
40
41 Translates: setup_grsett.f#SETUP_GRSETT (7be4133)
42
43 Arguments: dt (s), stot (g), hqpr (d ln P/dr), hs1 (g): converted in
44 place or returned; hr, hd, ht (logs); lc (convective flags); m; hcomp;
45 hru, htu (filled: r, T in B&L units); ibegin, iend, lallcz (only
46 set); cod1, cod2, qcod1x, qcod2x, cod1z, cod2z, qcod1z, qcod2z
47 (filled, index 0 unused).
48
49 Returns (dt, stot, ibegin, iend, lallcz).
50
51 """
52
53 c = constants_mod
54 n = nmlpar_mod
55 cf = confac_mod
56 sdel = scrtch_mod.sdel
57
58 # Solar radius (cm) and seconds per year, Bahcall and Loeb's values
59 # (Fortran lines 107–108).
60 crsun_bah = 6.9598e10
61 csecyr_bah = 3.1558e7
62
63 # LALLCZ: fully convective (or no shell qualifies), no settling
64 # (Fortran line 110).
65 lallcz = False
66
67 # Convective core (Fortran lines 112–126).
68 if lc[1]:
69 for i in range(2, m + 1):
70 if not lc[i]:
71 break # go to 20
72 else:
73 lallcz = True
74 iounits_mod.write(iounits_mod.ishort,
75 " FULLY CONVECTIVE MODEL - NO SETTLING")
76 return dt, stot, ibegin, iend, lallcz # go to 9999
77 # Overshoot (to be added).
78 ibegin = i - 1
79 else:
80 ibegin = 1
81
82 # Hydrogen-exhausted core (MHP 6/90) (Fortran lines 128–137).
83 for i in range(ibegin, m + 1):
84 if hcomp[1, i] > n.xmin:
85 break # go to 25
86 else:
87 iounits_mod.write(iounits_mod.ishort,
88 f" X BELOW {n.xmin:9.6f} IN WHOLE MODEL-NO SETTLING")
89 lallcz = True
90 return dt, stot, ibegin, iend, lallcz
91 ibegin = i # label 25
92
93 # Convective envelope (Fortran lines 139–148).
94 if lc[m]:
95 i = m - 1
96 for i in range(m - 1, 1, -1):
97 if not lc[i]:
98 break # go to 40
99 else:
100 i = 1 # the Fortran's DO index after the last pass
101 # Overshoot (to be added).
102 iend = i + 1
103 else:
104 iend = m
105
106 # Helium-exhausted surface: the outer point is wherever Y > YMIN
107 # (Fortran lines 151–160).
108 for i in range(iend, 0, -1):
109 if hcomp[2, i] > n.ymin:
110 break # go to 47
111 else:
112 iounits_mod.write(iounits_mod.ishort,
113 f" Y BELOW {n.ymin:9.6f} IN WHOLE MODEL-NO SETTLING")
114 lallcz = True
115 return dt, stot, ibegin, iend, lallcz
116 iend = i # label 47
117
118 # Conversion factors (Fortran lines 165–169).
119 cf.con_rad = 1.0 / crsun_bah
120 cf.con_mass = 1.0e-2 * cf.con_rad**3
121 cf.con_temp = 1.0e-7
122 # Includes the factor 2.2 from ln Lambda. Question (see the page): ln
123 # Lambda counted twice?
124 cf.con_time = 2.7e13 * csecyr_bah
125
126 # To Bahcall and Loeb's units (Fortran lines 172–181).
127 for i in range(1, m + 1):
128 hru[i] = math.exp(c.cln * hr[i]) * cf.con_rad
129 htu[i] = math.exp(c.cln * ht[i]) * cf.con_temp
130 hs1[i] = hs1[i] * cf.con_mass
131 hqpr[i] = hqpr[i] / cf.con_rad
132 dt = dt / cf.con_time
133 stot = stot * cf.con_mass
134
135 # Diffusion coefficients, for every shell (BC 5/90) (Fortran lines
136 # 189–327).
137 for i in range(1, m + 1): # loop 60
138 # The Coulomb logarithm (Fortran lines 191–204). Question (see the
139 # page): which ILAMBDA is recommended?
140 x = hcomp[1, i]
141 if n.ilambda == 2:
142 # Noerdlinger (1977).
143 ln_lambda = (-1.97e1 - 0.5 * math.log(1.0 / (0.75 * x + 0.25))
144 - 0.5 * hd[i] * c.cln + 1.5 * ht[i] * c.cln)
145 elif n.ilambda == 3:
146 # Loeb (1989).
147 ln_lambda = -1.9105747e1 - 0.50 * hd[i] * c.cln \
148 + 1.5 * ht[i] * c.cln
149 else:
150 ln_lambda = 2.2
151
152 # Fortran lines 206–210.
153 fac = n.fgry * hru[i]**2 * htu[i]**2.5 / ln_lambda
154 z = hcomp[3, i] + hcomp[4, i]
155 zz = hcomp[3, i]
156 x2 = x * x
157
158 if not n.lthoul:
159 # Bahcall and Loeb (Fortran lines 211–222).
160 xz = x * z
161 x3 = x2 * x # noqa: F841 (unused in the Fortran too)
162 fac2 = 5.4 + 6.3 * x - 4.5 * x2
163 # Question (see the page): +0.32 here, -0.32 in the comment.
164 cod1[i] = fac * hqpr[i] * (x - x2 - xz) * (
165 1.25 + sdel[2, i] * 6.0 * (x + 0.32) / fac2)
166 cod2[i] = fac * (x + 3.0) / (5.0 * x2 + 8.0 * x + 3.0)
167 qcod1x[i] = fac * hqpr[i] * (
168 (1.0 - 2.0 * x - z)
169 * (1.25 + (6.0 * sdel[2, i] * (x + 0.32)) / fac2)
170 + (x - x2 - xz) * 6.0 * sdel[2, i]
171 * (3.384 + 2.88 * x + 4.5 * x2) / fac2**2)
172 qcod2x[i] = (-fac * (5.0 * x2 + 3.0e1 * x + 2.1e1)
173 / (5.0 * x2 + 8.0 * x + 3.0)**2)
174 else:
175 # Thoul et al.: A_P and A_T from THDIFF or the fits (Fortran
176 # lines 224–281).
177 xfrac[1] = hcomp[1, i]
178 xfrac[2] = hcomp[2, i]
179 xfrac[3] = hcomp[3, i]
180 if not n.lthoulfit:
181 if n.ilambda == 4:
182 _pair_coulomb_logs(hd[i], ht[i])
183 else:
184 for ii in range(1, NSPEC + 1):
185 for jj in range(1, NSPEC + 1):
186 tcl[ii, jj] = ln_lambda
187 thdiff(NSPEC, ATOMWT, ZSPEC, xfrac, tcl, tap, tat, tac)
188 ap = -tap[1]
189 at = -sdel[2, i] * tat[1]
190 else:
191 ap = 1.58 - 2.42 * x + 0.844 * x2
192 at = sdel[2, i] * (1.90 - 2.69 * x + 0.805 * x2)
193
194 # A_C and the derivatives, from the fits (Fortran lines
195 # 282–285). Question (see the page): derivatives from the fits
196 # always.
197 ac = 1.15 - 1.42 * x + 0.647 * x2
198 qapx = -2.42 + 1.688 * x
199 qatx = sdel[2, i] * (-2.69 + 1.61 * x)
200 qacx = -1.42 + 1.294 * x
201
202 # Mimic mixing, to reduce settling (FD 10/09) (Fortran lines
203 # 288–291). Suspected bug (see the page): the derivatives lack
204 # CSTMIXING.
205 cod1[i] = n.cstmixing * fac * hqpr[i] * x * (ap + at)
206 cod2[i] = n.cstmixing * fac * ac
207 qcod1x[i] = fac * hqpr[i] * (ap + at + x * (qapx + qatx))
208 qcod2x[i] = fac * qacx
209
210 # Metals: Thoul et al.'s coefficients for fully ionized iron
211 # (Fortran lines 295–319); PARMIN sets LTHOUL with LDIFZ.
212 if n.ldifz:
213 fac = n.fgrz * hru[i]**2 * htu[i]**2.5 / ln_lambda
214 if n.lthoul:
215 if n.lthoulfit:
216 ap = -0.157 - 0.511 * x + 0.389 * x2
217 at = sdel[2, i] * (-1.36 - 1.42 * x + 0.549 * x2)
218 else:
219 ap = -tap[3]
220 at = -sdel[2, i] * tat[3]
221 ah = -0.0375 - 0.193 * x + 0.107 * x2
222 cod1z[i] = (n.cstdiffmix * n.cstmixing * fac * hqpr[i]
223 * zz * (ap + at))
224 # Positive diffusion coefficients needed.
225 cod2z[i] = n.cstmixing * abs(fac * ah)
226 # Suspected bug (see the page): QCOD1Z lacks CSTDIFFMIX.
227 qcod1z[i] = n.cstmixing * fac * hqpr[i] * (ap + at)
228 qcod2z[i] = 0.0
229
230 # Noerdlinger's ln Lambda adds a term to d(D1)/dX (Fortran lines
231 # 323–326).
232 if n.ilambda == 2:
233 qcod1x[i] = qcod1x[i] + cod1[i] * 1.5 / (
234 ln_lambda * (3.0 * x + 1.0))
235
236 return dt, stot, ibegin, iend, lallcz # label 9999
237
238
239def _pair_coulomb_logs(hdi: float, hti: float) -> None:
240 """ILAMBDA = 4: a Coulomb logarithm for each pair of species, from the
241 larger of the Debye length and the interionic distance (into tcl)
242 (Fortran lines 229–267).
243
244 """
245
246 c = constants_mod
247 rho = math.exp(c.cln * hdi)
248 t = math.exp(c.cln * hti)
249
250 # Concentrations from mass fractions (Fortran lines 232–239).
251 zxa = 0.0
252 for ii in range(1, NSPEC):
253 zxa = zxa + ZSPEC[ii] * xfrac[ii] / ATOMWT[ii]
254 for ii in range(1, NSPEC):
255 cfrac[ii] = xfrac[ii] / (ATOMWT[ii] * zxa)
256 cfrac[NSPEC] = 1.0
257
258 # Electron density from the mass density (Fortran lines 241–245).
259 ac = 0.0
260 for ii in range(1, NSPEC + 1):
261 ac = ac + ATOMWT[ii] * cfrac[ii]
262 ne = rho / (1.6726e-24 * ac)
263
264 # Interionic distance (Fortran lines 247–251).
265 ni = 0.0
266 for ii in range(1, NSPEC):
267 ni = ni + cfrac[ii] * ne
268 ao = (0.23873 / ni)**c.cc13
269
270 # Debye length (Fortran lines 253–257).
271 cz = 0.0
272 for ii in range(1, NSPEC + 1):
273 cz = cz + cfrac[ii] * ZSPEC[ii]**2
274 lambdad = 6.9010 * math.sqrt(t / (ne * cz))
275
276 # The Coulomb logarithms (Fortran lines 259–267).
277 lam = max(lambdad, ao)
278 for ii in range(1, NSPEC + 1):
279 for jj in range(1, NSPEC + 1):
280 xij = 2.3939e3 * t * lam / abs(ZSPEC[ii] * ZSPEC[jj])
281 tcl[ii, jj] = 0.81245 * math.log(1.0 + 0.18769 * xij**1.2)