1C
2C
3C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
4C QATM
5C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
6 SUBROUTINE QATM(X0,Y,DYDX,B,FPL,FTL,GL,LATMO,LDERIV,LOCOND,LSAVE,
7 * * RL,TEFFL,X,Z,KATM,KSAHA)
8C 10/14/26 MHP via Claude
9C code changed to convert COMMON/PULSE2/ into PULSE2_MOD.
10 USE PULSE2_MOD
11C 10/14/26 MHP via Claude
12C code changed to convert COMMON/PULSE1/ into PULSE1_MOD.
13 USE PULSE1_MOD
14C 10/14/26 MHP via Claude
15C code changed to convert COMMON/ATMPRT/ into ATMPRT_MOD.
16 USE ATMPRT_MOD
17C 10/14/26 MHP via Claude
18C code changed to convert COMMON/ATMOS/ into ATMOS_MOD.
19 USE ATMOS_MOD
20C 10/14/26 MHP via Claude
21C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
22 USE NMLPAR_MOD
23C 10/14/26 MHP via Claude
24C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
25 USE CONSTANTS_MOD
26C 10/20/26 MHP via Claude
27C code changed to replace implicit typing with IMPLICIT NONE and
28C explicit declarations.
29 IMPLICIT NONE
30 REAL*8 AMU,B,BETA,BETA1,BETA14,D,DELA,DL,DYDX,EMU,ETA,FPL,FTL,
31 * * FXION,G,GL,HRA,O,OL,P,PL,QAP,QAT,QCP,QCPP,QCPT,QDP,QDT,
32 * * QDTP,QDTT,QOD,QOT,RL,RMU,T,TAU,TEFFL,TL,TTAUL0,TTAUL1,X,X0,
33 * * Y,YY,Z
34 INTEGER KATM,KSAHA
35 LOGICAL*4 LATMO,LDERIV,LOCOND,LSAVE
36C QATM CALCULATES THE DERIVATIVE D(P)/D(TAU), USING THE EDDINGTON
37C APPROXIMATION FOR A T-TAU RELATION.
38C IT ALSO RETURNS TL,O, AND FXION FOR OUTPUT PURPOSES
39C Q(TAU) = 0.6666667
40
41C 10/13/26 MHP via Claude: removed the unused COMMON/IOUNITS/ declaration
42C (no member referenced here; residue of the obsolete-option removals).
43C 10/12/26 MHP via Claude
44C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
45C namelist variables that the physics routines read from 27 COMMON
46C blocks which also held derived or working members. Those blocks keep
47C only their non-namelist members; five of them -- NEWMX, VMULT,
48C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
49C Derivation-only namelist variables from the same blocks went to
50C COMMON/NMLBYPASS/ instead, not here.
51C
52C Declared identically in all 121 files that hold any of these members.
53C Generated from one member list, so every copy is byte-identical; the
54C linker's 'size of symbol changed' warning is the check that they are.
55C 10/13/26 MHP via Claude: removed the unused COMMON/NEWOPAC/ declaration
56C (no member referenced here; residue of the obsolete-option removals).
57 DIMENSION Y(3),DYDX(3),FXION(3)
58C 10/13/26 MHP via Claude
59C code changed to drop COMMON/PULSE/, declared here but never used.
60C 9/25/26 MHP via Claude
61C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
62C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
63 SAVE
64
65C EDDINGTON APPROXIMATION
66 TTAUL0(YY) = TEFFL - 0.031235D0 + 0.25D0*DLOG10(YY + CC23)
67
68C KRISHNA-SWAMY APPROXIMATION (BASED ON FIT TO SOLAR ATMOSPHER)
69C SEE KRISHNA-SWAMY, AP.J. 1966, 145, 176.
70 TTAUL1(YY) = TEFFL - 0.031235D0 + 0.25D0*DLOG10(YY +
71 1 1 1.39D0 - 0.815D0*EXP(-2.54D0*YY) - 0.025D0*EXP(-30.0D0*YY))
72
73 G = DEXP(CLN*GL)*FPL
74 TAUL = X0
75 TAU = DEXP(CLN*TAUL)
76C USE KTTAU TO IMPLIMENT FUTURE T TAU RELATIONS
77 IF (KTTAU .EQ. 0) THEN
78 TL = TTAUL0(TAU)
79 ELSE IF (KTTAU .EQ. 1) THEN
80 TL = TTAUL1(TAU)
81 ELSE IF (KTTAU .EQ. 2) THEN
82 TL = TEFFL + HRA(TAU) - HRAS
83 END IF
84 PL = Y(1)
85C 9/22/26 MHP via Claude
86C code changed to remove the MHD equation of state
87 CALL EQSTAT(TL,T,PL,P,DL,D,X,Z,BETA,BETA1,BETA14,FXION,RMU,AMU,
88 * * EMU,ETA,QDT,QDP,QCP,DELA,QDTT,QDTP,QAT,QAP,QCPT,QCPP,LDERIV,
89 * * LATMO,KSAHA)
90 CALL GETOPAC(DL, TL, X, Z, O, OL, QOD, QOT,FXION)
91 DYDX(1) = G*TAU/(P*O)
92 KATM = KATM + 1
93 AP = PL
94 AT = TL
95 IF(LSAVE .OR. LPUMOD) THEN
96 AD = DL
97 AO = O
98 AFXION(1) = FXION(1)
99 AFXION(2) = FXION(2)
100 AFXION(3) = FXION(3)
101 QTL = TL
102 QT = DEXP(CLN*TL)
103 QPL = PL
104 QP = DEXP(CLN*PL)
105 QDL = DL
106 QD = DEXP(CLN*DL)
107 QO = O
108 QOL = OL
109 QQDP = QDP
110 QQED = 0.0D0
111 QQOD = QOD
112 QQOT = QOT
113 QDEL = 0.0D0
114 QQDT = QDT
115 QDELA = DELA
116 QQCP = QCP
117 QRMU = RMU
118 QEMU = EMU
119 ENDIF
120
121C KC 2025-05-31 THESE MUST BE RETAINED FOR EXTERNAL PROCEDURE COMPATIBILITY.
122 IF (.FALSE.) PRINT *, B, FTL, LOCOND, RL
123
124 RETURN
125 END
1"""Python version of qatm.f (YREC 7be4133): the right-hand side of the
2atmosphere integration, d log P / d log tau."""
3
4import math
5
6import numpy as np
7
8from pyrec import atmos_mod
9from pyrec import atmprt_mod
10from pyrec import constants_mod
11from pyrec import nmlpar_mod
12from pyrec import pulse1_mod
13from pyrec import pulse2_mod
14from pyrec.eqstat import eqstat
15from pyrec.getopac import getopac
16from pyrec.hra import hra
17
18# Locals kept between calls (SAVE): TL keeps its value when KTTAU is not
19# 0, 1 or 2.
20tl = 0.0
21
22
23def qatm(x0: float, y: np.ndarray, dydx: np.ndarray, b: float, fpl: float, ftl: float, gl: float, latmo: bool,
24 lderiv: bool, locond: bool, lsave: bool, rl: float, teffl: float, x: float, z: float, katm: int,
25 ksaha: int) -> tuple[int, int]:
26 """Derivative of log P with respect to log tau in the atmosphere, from
27 a T-tau relation (Eddington, Krishna Swamy or the Harvard reference
28 atmosphere, by KTTAU) and hydrostatic equilibrium dP/dtau = g/kappa.
29 Also stores the point for output in atmprt_mod and pulse2_mod.
30
31 Translates: qatm.f#QATM (7be4133)
32
33 Arguments: x0 = log tau; y (array of 3, index 0 unused), y[1] = log P;
34 the surface gravity gl, distortion factor fpl, teffl, x, z; lsave
35 (store the point for output). b, ftl, locond and rl are not used: the
36 argument list is that of the derivative routine called by bsstep and
37 mmid. Arrays changed in place: dydx (dydx[1] set).
38
39 Returns (katm, ksaha): the atmosphere-call counter, incremented, and
40 the counter of Saha calls, from eqstat.
41
42 """
43
44 global tl
45 fxion = np.zeros(4) # index 0 unused
46
47 # Statement functions: Eddington, and Krishna Swamy (1966, ApJ 145, 176)
48 # (Fortran lines 65–71).
49 def ttaul0(yy):
50 return teffl - 0.031235 + 0.25 * math.log10(yy + constants_mod.cc23)
51
52 def ttaul1(yy):
53 return teffl - 0.031235 + 0.25 * math.log10(
54 yy + 1.39 - 0.815 * math.exp(-2.54 * yy)
55 - 0.025 * math.exp(-30.0 * yy))
56
57 # T from the T-tau relation (Fortran lines 73–83). For KTTAU 3-5 TL
58 # would keep its last value, but envint does not call qatm with them.
59 g = math.exp(constants_mod.cln * gl) * fpl
60 atmprt_mod.taul = x0
61 tau = math.exp(constants_mod.cln * atmprt_mod.taul)
62 if nmlpar_mod.kttau == 0:
63 tl = ttaul0(tau)
64 elif nmlpar_mod.kttau == 1:
65 tl = ttaul1(tau)
66 elif nmlpar_mod.kttau == 2:
67 tl = teffl + hra(tau) - atmos_mod.hras
68
69 # Density and opacity, then d log P / d log tau (Fortran lines 84–94).
70 pl = y[1]
71 (t, p, dl, d, beta, beta1, beta14, rmu, amu, emu, eta, qdt, qdp, qcp,
72 dela, qdtt, qdtp, qat, qap, qcpt, qcpp, ksaha) = eqstat(
73 tl, 0.0, pl, 0.0, 0.0, 0.0, x, z, 0.0, 0.0, 0.0, fxion, 0.0, 0.0,
74 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
75 lderiv, latmo, ksaha)
76 o, ol, qod, qot = getopac(dl, tl, x, z, 0.0, 0.0, 0.0, 0.0, fxion)
77 dydx[1] = g * tau / (p * o)
78 katm = katm + 1
79 atmprt_mod.ap = pl
80 atmprt_mod.at = tl
81
82 # Store the point for output (Fortran lines 95–119).
83 if lsave or pulse1_mod.lpumod:
84 atmprt_mod.ad = dl
85 atmprt_mod.ao = o
86 atmprt_mod.afxion[1] = fxion[1]
87 atmprt_mod.afxion[2] = fxion[2]
88 atmprt_mod.afxion[3] = fxion[3]
89 q = pulse2_mod
90 q.qtl = tl
91 q.qt = math.exp(constants_mod.cln * tl)
92 q.qpl = pl
93 q.qp = math.exp(constants_mod.cln * pl)
94 q.qdl = dl
95 q.qd = math.exp(constants_mod.cln * dl)
96 q.qo = o
97 q.qol = ol
98 q.qqdp = qdp
99 q.qqed = 0.0
100 q.qqod = qod
101 q.qqot = qot
102 q.qdel = 0.0
103 q.qqdt = qdt
104 q.qdela = dela
105 q.qqcp = qcp
106 q.qrmu = rmu
107 q.qemu = emu
108
109 return katm, ksaha