1C
2C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
3C COEFFT
4C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
5 SUBROUTINE COEFFT(DELTS,M,HD,HHA,HHB,HHC,HL,HMAX,HP,HPP,HR,HS,HS1,
6 * *HS2,HT,HTT,HCOMP,LC,TLUMX,LATMO,LDERIV,LMIX,LOCOND,KSAHA,
7C *MODEL,FP,FT,HKEROT,HKEROTO,JENV,TEFFL) ! KC 2025-05-31
8 * *FP,FT,HKEROT,HKEROTO,JENV,TEFFL,CMIXL)
9C 11/02/26 MHP via Claude
10C code changed to make QDT and QDP locals. EQSTAT sets them at every
11C point before use, so the values passed in from CRRECT were never read.
12C 10/15/26 MHP via Claude
13C code changed to take JSON from DIMENSIONS_MOD instead of declaring
14C PARAMETER(JSON=5000) here.
15 USE DIMENSIONS_MOD
16C 10/14/26 MHP via Claude
17C code changed to convert COMMON/SOUND/ into SOUND_MOD.
18 USE SOUND_MOD
19C 10/14/26 MHP via Claude
20C code changed to convert COMMON/SCRTCH/ into SCRTCH_MOD.
21 USE SCRTCH_MOD
22C 10/14/26 MHP via Claude
23C code changed to convert COMMON/ROTEN/ into ROTEN_MOD.
24 USE ROTEN_MOD
25C 10/14/26 MHP via Claude
26C code changed to convert COMMON/ROTDER/ into ROTDER_MOD.
27 USE ROTDER_MOD
28C 10/14/26 MHP via Claude
29C code changed to convert COMMON/PULSE2/ into PULSE2_MOD.
30 USE PULSE2_MOD
31C 10/14/26 MHP via Claude
32C code changed to convert COMMON/PULSE1/ into PULSE1_MOD.
33 USE PULSE1_MOD
34C 10/14/26 MHP via Claude
35C code changed to convert COMMON/MASSCHG2/ into MASSCHG2_MOD.
36 USE MASSCHG2_MOD
37C 10/14/26 MHP via Claude
38C code changed to convert COMMON/FLUXES/ into FLUXES_MOD.
39 USE FLUXES_MOD
40C 10/14/26 MHP via Claude
41C code changed to convert COMMON/DPMIX/ into DPMIX_MOD.
42 USE DPMIX_MOD
43C 10/14/26 MHP via Claude
44C code changed to convert COMMON/DEBHU/ into DEBHU_MOD.
45 USE DEBHU_MOD
46C 10/14/26 MHP via Claude
47C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
48 USE NMLPAR_MOD
49C 10/14/26 MHP via Claude
50C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
51 USE CONSTANTS_MOD
52C 10/20/26 MHP via Claude
53C code changed to replace implicit typing with IMPLICIT NONE and
54C explicit declarations.
55 IMPLICIT NONE
56 REAL*8 AMU,B,BE7MFLOC,BETA,BETA14,BETAI,CCCQL,CHRH,CHT,CMIXL,CV,D,
57 * * DEL,DELA,DELR,DELTS,DELTSI,DL,DT,E,EALPCA,ECA,EG,EGG11,
58 * * EGG22,EGG33,EGG44,EGG55,EGNEUT,EGRAV,EMU,ENTR,ENTR1,ENTR2,
59 * * ENTR3,ENU,ESUMI,ETA,ETOT,FP,FPL,FT,FTL,FXION,HCOMP,HD,HF1,
60 * * HF2,HHA,HHB,HHC,HKEROT,HKEROTO,HL,HMAX,HP,HPP,HPPP,HR,HR1,
61 * * HR10,HR11,HR12,HR13,HR2,HR3,HR4,HR5,HR6,HR7,HR8,HR9,HS,HS1,
62 * * HS2,HT,HTT,HTTT,O,OL,P,PL,QACP,QACR,QACT,QAP,QAT,QCP,QCPP,
63 * * QCPT,QDP,QDT,QDTP,QDTT,QED,QET,QL,QL0,QLP,QLP0,QLT,QLT0,
64 * * QOD,QOT,QP0,QPP,QPP0,QPR,QPR0,QR,QR0,QRP,QRP0,QRR,QRR0,QRT,
65 * * QRT0,QT0,QTEMP,QTL0,QTP,QTP0,QTR,QTR0,QTT,QTT0,RL,RMU,SL,
66 * * SUM1,T,TEFFL,THL,TIME,TIMEI,TL,TLUMX,VEL,X,XBE9,XC12,XC13,
67 * * XH2,XHE3,XLI6,XLI7,XN14,XN15,XO16,XO17,XO18,Y,Z
68 INTEGER IM,IM1,IU,J,JENV,KSAHA,M
69 LOGICAL*4 LATMO,LC,LCONV,LDERIV,LMIX,LNTRPY,LOCOND
70C 2/91 MHP FLAG TO TOGGLE BETWEEN OLD/NEW ENERGY GENERATION ROUTINES
71C ADDED (COMMON BLOCK NEWENG).
72
73C 10/13/26 MHP via Claude: removed the unused COMMON/IOUNITS/ declaration
74C (no member referenced here; residue of the obsolete-option removals).
75C 10/11/26 MHP via Claude
76C code changed to remove LSCRIB from COMMON/CCOUT/: it was declared
77C positionally in all 17 files sharing this block but never read or
78C written in executable code anywhere, and no namelist file sets it.
79C 10/12/26 MHP via Claude
80C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
81C namelist variables that the physics routines read from 27 COMMON
82C blocks which also held derived or working members. Those blocks keep
83C only their non-namelist members; five of them -- NEWMX, VMULT,
84C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
85C Derivation-only namelist variables from the same blocks went to
86C COMMON/NMLBYPASS/ instead, not here.
87C
88C Declared identically in all 121 files that hold any of these members.
89C Generated from one member list, so every copy is byte-identical; the
90C linker's 'size of symbol changed' warning is the check that they are.
91C 10/13/26 MHP via Claude: removed the unused COMMON/CCOUT/ declaration
92C (no member referenced here; residue of the obsolete-option removals).
93C 9/25/26 MHP via Claude
94C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
95C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
96C 9/24/26 MHP via Claude
97C code changed to pass CMIXL as an explicit argument instead of via
98C common block, to reduce implicit global state ahead of the F90
99C module conversion
100C 10/13/26 MHP via Claude
101C code changed to drop COMMON/CTLIM/, declared here but never used.
102C 10/12/26 MHP via Claude
103C code changed to remove COMMON/OPTAB/ entirely. Once OPTOL moved to the
104C consolidated namelist block, every remaining member was write-only:
105C ZSI appeared only in a DATA statement in parmin.f, and IDT and IDD were
106C assigned the constants 15 and 5 in coefft.f, envint.f, physic.f and
107C starin.f and read nowhere in the code. They are leftovers from the
108C removed opacity-table interpolation schemes.
109C DBG PULSE
110C 10/13/26 MHP via Claude
111C code changed to drop COMMON/PULSE/, declared here but never used.
112C DBG
113C*** MHP 5/90 ADD COMMON BLOCK FOR SOLAR NEUTRINO I/O
114C*** MHP 5/91 ADD COMMON BLOCK FOR ENERGY FROM ALPHA CAPTURE REACTIONS
115C AND LOSSES FROM NEUTRINO-COOLED CORES IN EVOVLED STARS.
116C 10/13/26 MHP via Claude
117C code changed to replace COMMON/NEWEPS/ with explicit arguments: engeb.f
118C computes EALPCA and ENU, and coefft.f and ytime.f read them right after
119C their own CALL ENGEB, so they are returned as arguments. main.f, the
120C third caller, passes locals it does not use.
121C DBG 7/92 COMMON BLOCK ADDED TO COMPUTE DEBYE-HUCKEL CORRECTION.
122C DBG 7/95 To store variables for pulse output
123C MHP 7/96 COMMON BLOCK ADDED FOR SOUND SPEED
124C MHP 06/02 COMMON BLOCK ADDED FOR DERIVATIVES OF
125C CAPPA AND EPSILON
126C 10/13/26 MHP via Claude
127C code changed to drop the write-only members SQOD and SQED from
128C COMMON/ROTDER/. coefft.f assigned both and nothing ever read them;
129C setupv.f, the block's only reader, uses SQOT, SQET and FRACNUC. That
130C frees 10,000 words. The block itself stays: coefft.f and setupv.f sit
131C in different phases -- setupv.f is reached via seculr.f -- so passing
132C the rest explicitly would mean threading 15,000-word arrays through
133C main.f and GETW.
134
135C JVS 10/11 Common block for He3+He3 luminosity
136C JVS end
137
138 DIMENSION FXION(3),EG(6),TLUMX(8),HD(JSON),HHA(4,2,JSON),
139 * *HHB(4,JSON),HHC(JSON),HL(JSON),HMAX(4),HP(JSON),HPP(JSON),
140 * *HR(JSON),HS(JSON),HS1(JSON),HS2(JSON),HT(JSON),HTT(JSON),LC(JSON),
141 * *HCOMP(15,JSON),FP(JSON),FT(JSON)
142 DIMENSION HF1(JSON),HF2(JSON),HR1(JSON),HR2(JSON),HR3(JSON),
143 * *HR4(JSON),HR5(JSON),HR6(JSON),HR7(JSON),HR8(JSON),HR9(JSON),
144 * *HR10(JSON),HR11(JSON),HR12(JSON),HR13(JSON)
145 DIMENSION HKEROT(JSON),HKEROTO(JSON)
146 SAVE
147
148C 7/91 MHP
149C ZERO OUT SOLAR NEUTRINO FLUXES.
150C FLUXTOT = TOTAL FLUX OF EACH OF THE NEUTRINOS PRODUCED IN THE SUN
151 IF(LSNU) THEN
152 DO 5 J = 1,10
153 FLUXTOT(J) = 0.0D0
154 5 5 CONTINUE
155 ENDIF
156C MHP 10/02 QFPR,QFTR NOT USED - OMIT
157c IF(.NOT.LROT) THEN
158C QFPR = 0.0D0
159C QFTR = 0.0D0
160c ENDIF
161 LOCOND = .TRUE.
162 LDERIV = .TRUE.
163 LATMO = .FALSE.
164 LMIX = .FALSE.
165 LNTRPY = DELTS.GT.0.0D0
166 IF(LNTRPY) THEN
167 DELTSI = 1.0D0/DELTS
168 TIME = 3.1558D7
169 TIMEI = 3.1688D-8
170 ENDIF
171 DO 10 J = 1,8
172 TLUMX(J) = 0.0D0
173 10 10 CONTINUE
174 DO 30 IM = 1,M
175C SET UP LOCAL VARIABLES FOR CALLS TO BASIC PHYSICS ROUTINES
176 THL = 0.0D0
177 SL = HS(IM)
178 TL = HT(IM)
179 PL = HP(IM)
180 RL = HR(IM)
181 B = HL(IM)
182 X = HCOMP(1,IM)
183 Y = HCOMP(2,IM)
184 Z = HCOMP(3,IM)
185 XHE3 = HCOMP(4,IM)
186 XC12 = HCOMP(5,IM)
187 XC13 = HCOMP(6,IM)
188 XN14 = HCOMP(7,IM)
189 XN15 = HCOMP(8,IM)
190 XO16 = HCOMP(9,IM)
191 XO17 = HCOMP(10,IM)
192 XO18 = HCOMP(11,IM)
193C MHP 05/02 DEFINE THESE ALWAYS; THEY
194C ARE PASSED TO THE SR ANYWAY.
195C IF(LEXCOM) THEN
196 XH2 = HCOMP(12,IM)
197 XLI6 = HCOMP(13,IM)
198 XLI7 = HCOMP(14,IM)
199 XBE9 = HCOMP(15,IM)
200C ENDIF
201 IU = IM
202 DL = HD(IM)
203 FPL = FP(IM)
204 FTL = FT(IM)
205C 9/22/26 MHP via Claude
206C code changed to remove the MHD equation of state
207 IF (LDH) THEN
208 XXDH = HCOMP(1,IM)
209 YYDH = HCOMP(2,IM)+HCOMP(4,IM)
210 ZZDH = HCOMP(3,IM)
211 ZDH(1) = HCOMP(5,IM)+HCOMP(6,IM)
212 ZDH(2) = HCOMP(7,IM)+HCOMP(8,IM)
213 ZDH(3) = HCOMP(9,IM)+HCOMP(10,IM)+HCOMP(11,IM)
214 END IF
215 CALL EQSTAT(TL,T,PL,P,DL,D,X,Z,BETA,BETAI,BETA14,FXION,RMU,
216 * * AMU,EMU,ETA,QDT,QDP,QCP,DELA,QDTT,QDTP,QAT,QAP,QCPT,
217 * * QCPP,LDERIV,LATMO,KSAHA)
218C DBG 12/95 GET OPACITY
219 CALL GETOPAC(DL, TL, X, Z, O, OL, QOD, QOT, FXION)
220 IOVIM = IM
221 CALL TPGRAD(TL,T,PL,P,D,RL,SL,B,O,QDT,QDP,QOT,QOD,QCP,DEL,
222 * * DELR,DELA,QDTT,QDTP,QAT,QAP,QACT,QACP,QACR,QCPT,QCPP,
223 * * VEL,LDERIV,LCONV,FPL,FTL,TEFFL,CMIXL)
224 HD(IM) = DL
225C COMPUTE DERIVATIVES
226c IF(LROT) THEN
227C CALCULATE D(LOG FP)/D(LOG R) AND D(LOG FT)/D(LOG R)
228c IF(IM.GT.1) THEN
229c IF(IM.LT.M) THEN
230c QFPR = (DLOG(FP(IM+1)) - DLOG(FP(IM-1)))/
231c * (CLN*(HR(IM+1) - HR(IM-1)))
232c QFTR = (DLOG(FT(IM+1)) - DLOG(FT(IM-1)))/
233c * (CLN*(HR(IM+1) - HR(IM-1)))
234c ELSE
235c QFPR = (DLOG(FP(M)) - DLOG(FP(M-1)))/
236c * (CLN*(HR(M) - HR(M-1)))
237c QFTR = (DLOG(FT(M)) - DLOG(FT(M-1)))/
238c * (CLN*(HR(M) - HR(M-1)))
239c ENDIF
240c ELSE
241c QFPR = (DLOG(FP(2)) - DLOG(FP(1)))/
242c * (CLN*(HR(2) - HR(1)))
243c QFTR = (DLOG(FT(2)) - DLOG(FT(1)))/
244c * (CLN*(HR(2) - HR(1)))
245c ENDIF
246c ENDIF
247 QTEMP = C4PIL + RL + RL + RL
248 QR =+DEXP(CLN*(SL - DL - QTEMP))
249 QRR = - QR - QR - QR
250 QRP = -QR*QDP
251 QRT = -QR*QDT
252 QP =-DEXP(CLN*(CGL + SL + SL - PL - QTEMP - RL ))*FP(IM)
253C QPR = -QP - QP - QP - QP*(1.0D0 - QFPR)
254 QPR = -QP - QP - QP - QP
255 QPP = -QP
256 LC(IM) = LCONV
257 QT = DEL*QP
258 QTR = -QT - QT - QT - QT
259C QTR = -QT - QT - QT - QT*(1.0D0 - QFTR)
260 IF(.NOT.LCONV) THEN
261C TEMPERATURE GRADIENT IS RADIATIVE
262 QTL = CLNI*QT/B
263 QTP = QT*QOD*QDP
264 QTT = QT*(-4.0D0 + QOT + QOD*QDT)
265 ELSE
266C TEMPERATURE GRADIENT IS CONVECTIVE
267 QTL = 0.0D0
268 QTP = QT*(-1.0D0 + QACP)
269 QTT = QT*QACT
270 QTR = QTR + QT*QACR
271 ENDIF
272 QL = 0.0D0
273 QLT = 0.0D0
274 QLP = 0.0D0
275C 10/30/26 MHP via Claude
276C code changed to zero the epsilon derivatives below the burning cutoff.
277C They kept the last burning shell's values, which reached SQET (read
278C by SETUPV in rotating runs) and the pulse arrays.
279 QED = 0.0D0
280 QET = 0.0D0
281 IF(TL.GT.TCUT(1)) THEN
282C SET UP NUCLEAR ENERGY TERMS
283C 10/13/26 MHP via Claude
284C code changed to pass BE7MFLOC for ENGEB's new BE7MASSFRACTION
285C argument, which replaces COMMON/BE7/. This routine does not use the
286C value; only main.f reads it.
287 CALL ENGEB(EGG11,EGG22,EGG33,EGG44,EGG55,QED,QET,SUM1,DL,
288C * TL,QDT,QDP,X,Y,Z,XHE3,XC12,XC13,XN14,XN15,XO16,XO17,
289C * XO18,XH2,XLI6,XLI7,XBE9,IU,HR1,HR2,HR3,HR4,HR5,HR6,HR7, ! KC 2025-05-31
290 * * TL,X,Y,XHE3,XC12,XC13,XN14,XO16,
291 * * XO18,XH2,IU,HR1,HR2,HR3,HR4,HR5,HR6,HR7,
292 * * HR8,HR9,HR10,HR11,HR12,HR13,HF1,HF2,BE7MFLOC,EALPCA,ENU)
293 E = SUM1
294 EG(1) = EGG11
295 EG(2) = EGG22
296 EG(3) = EGG33
297 EG(4) = EGG44
298 EG(5) = EGG55
299 EG(6) = ENU
300 ECA = EALPCA
301C 7/91 MHP
302C CONVERT NEUTRINO FLUX RATES (UNITS 10**10 ERGS PER GM)
303C TO UNITS OF 10**10 ERGS BY MULTIPLYING BY THE MASS.
304 IF(LSNU) THEN
305 DO 17 J = 1,10
306 FLUXTOT(J) = FLUXTOT(J) + FLUX(J)*HS2(IM)
307 17 17 CONTINUE
308 ENDIF
309 DO 20 J = 1,6
310 TLUMX(J) = TLUMX(J) + (HS2(IM)/CLSUN)*EG(J)
311 THL = THL + (HS2(IM)/CLSUN)*EG(J)
312 20 20 CONTINUE
313C 11/02/26 MHP via Claude
314C code changed to drop the never-read He3 luminosity arrays UMHE33
315C and UMHEAL (JVS 10/11).
316 TLUMX(8)=TLUMX(8)+(HS2(IM)/CLSUN)*ECA
317 THL = THL + (HS2(IM)/CLSUN)*ECA
318 QL = E
319 QLT = QLT + QET + QED*QDT
320 QLP = QLP + QED*QDP
321 ENDIF
322 IF(LNTRPY) THEN
323C SET UP ENTROPY TERMS
324 DT = DELTSI
325 IF(LMDOT.AND.DMDT0.GT.0.0D0)THEN
326 IF(IM.GE.JENV)THEN
327 HTTT = HTT(IM)+DLOGT
328 HPPP = HPP(IM)+DLOGP
329 ELSE
330 HTTT = HTT(IM)
331 HPPP = HPP(IM)
332 ENDIF
333 ELSE
334 HTTT = HTT(IM)
335 HPPP = HPP(IM)
336 ENDIF
337 IF(HCOMP(1,IM).GT.0.01D0 .AND. DELTS.LT.TIME)DT = TIMEI
338 ENTR1 = P*QDT/D
339 ENTR2 = ENTR1/DELA
340 ENTR = (ENTR2*HTTT - ENTR1*HPPP)*CLN
341 ENTR3 = ENTR2*CLN*HTTT
342C ENTR = (ENTR2*HTT(IM) - ENTR1*HPP(IM))*CLN
343C ENTR3 = ENTR2*CLN*HTT(IM)
344 EGRAV = DT*ENTR
345 HHC(IM) = EGRAV
346 TLUMX(7) = TLUMX(7) + (HS2(IM)/CLSUN)*EGRAV
347 QL = QL + EGRAV
348C 10/29/26 MHP via Claude
349C code changed to divide QDTP and QDTT by QDT. ENTR carries the factor
350C QDT (chi_T), so its log partials need dln(chi_T) = d(chi_T)/chi_T;
351C QDTT and QDTP are d(chi_T), as in QAT = ... + QDTT/QDT (EQSAHA, EQRELV).
352C Only the Jacobian changes; the residual QL was already right.
353 QLP = QLP + DT*(ENTR*(1.0D0-QDP+QDTP/QDT)-ENTR1 - ENTR3*QAP)
354 QLT = QLT + DT*(ENTR*(-QDT+QDTT/QDT) + ENTR2 - ENTR3*QAT)
355C 7/92 INCLUDE CHANGE IN ROTATIONAL KINETIC ENERGY IN ENERGY EQUATION.
356 IF(LROT)THEN
357 DEROT(IM) = DT*(HKEROT(IM)-HKEROTO(IM))/HS2(IM)
358 QL = QL - DEROT(IM)
359 ENDIF
360C ADD CHANGE IN ENTROPY FROM ACCRETED MATERIAL
361C IF(LMDOT.AND.DMDT0.GT.0.0D0)THEN
362C IF(IM.GE.JENV)THEN
363C QACC = - T*SCEN*DMDT0/CSECYR/SMASS0
364C WRITE(*,*)QL,QACC
365C QL = QL + QACC
366C ENDIF
367C ENDIF
368 ENDIF
369 CCCQL = CLNSUN*HS1(IM)
370 QL = CCCQL*QL
371 QLP = CCCQL*QLP
372 QLT = CCCQL*QLT
373 IF(IM.GT.1) THEN
374C REDUCE MATRIX FOR PAIR OF POINTS (IM-1,IM)
375 IM1 = IM
376 CALL REDUCE(IM1,HHA,HHB,HL,HMAX,HP,HR,HS,HT,QP0,QP,QPR0,
377 * * QPR,QPP0,QPP,QT0,QT,QTR0,QTR,QTL0,QTL,QTP0,QTP,QTT0,QTT,
378 * * QR0,QR,QRR0,QRR,QRP0,QRP,QRT0,QRT,QL0,QL,QLP0,QLP,QLT0,QLT)
379 ELSE
380C SETUP CENTRAL BOUNDARY CONDITIONS
381 HHA(3,1,1) = CC13*QDP
382 HHA(3,2,1) = CC13*QDT
383 HHB(3,1) = -CC13*(C4PI3L + DL - SL) - RL
384 HHA(4,1,1) = -QLP
385 HHA(4,2,1) = -QLT
386 HHB(4,1) = CLNI*QL - B
387 ENDIF
388 QP0 = QP
389 QPR0 = QPR
390 QPP0 = QPP
391 QT0 = QT
392 QTR0 = QTR
393 QTL0 = QTL
394 QTP0 = QTP
395 QTT0 = QTT
396 QR0 = QR
397 QRR0 = QRR
398 QRP0 = QRP
399 QRT0 = QRT
400 QL0 = QL
401 QLP0 = QLP
402 QLT0 = QLT
403C MHP 02/12 REMOVED RESTRICTIONS ON WHERE INTERMEDIATE VARIABLES
404C SUCH AS OPACITY ARE SAVED; PRIOR RESTRICTIONS WERE BASED ON OBSOLETE
405C MEMORY RESTRICTIONS IN LEGACY CODE
406C IF(LMDOT.AND.DMDT0.GT.0.0D0)THEN
407 SVEL(IM) = VEL
408C ENDIF
409C STORE VARIABLES FOR OUTPUT IN SCRIB2 IF MODEL IS TO BE PRINTED OUT
410C DBG PULSE STORE VARIABLES FOR PULSATION OUPUT
411C DBG 3/91 CHANGED TO ALWAYS EXECUTE THIS STUFF
412C LONG = MOD(MODEL,NPRT2).EQ.0 .OR. LROT
413C MHP 10/02 LSHORT NOT USED, OMIT
414C LSHORT = .NOT.LONG .AND. MOD(MODEL,NPRT1).EQ.0
415C ZERO OUT NUCLEAR ENERGY TERMS IF T < NUCLEAR CUTOFF.
416 IF(HT(IM).LT.TCUT(1)) THEN
417 SESUM(IM) = 0.0D0
418 SEG(7,IM) = HHC(IM)
419 DO J = 1,6
420 SEG(J,IM) = 0.0D0
421 END DO
422 ELSE
423C ELSE IF(LONG) THEN
424C LONG OUTPUT NEEDED
425 SESUM(IM) = EG(1)+EG(2)+EG(3)+EG(4)+EG(5)
426 SEG(6,IM) = EG(6)
427 SEG(7,IM) = HHC(IM)
428 IF(SESUM(IM).GT.1.0D-22) THEN
429 ESUMI = 1.0D0/SESUM(IM)
430 ELSE
431 ESUMI = 0.0D0
432 ENDIF
433 DO J = 1,5
434 SEG(J,IM) = EG(J)*ESUMI
435 END DO
436C SHORT OUTPUT ONLY
437C ELSE
438C SESUM(IM) = EG(1)+EG(2)+EG(3)+EG(4)+EG(5)
439C SEG(6,IM) = EG(6)
440C SEG(7,IM) = HHC(IM)
441 ENDIF
442 SBETA(IM) = BETA
443 SETA(IM) = ETA
444 LOCONS(IM) = LOCOND
445 SO(IM) = O
446 SDEL(1,IM) = DELR
447 SDEL(2,IM) = DEL
448 SDEL(3,IM) = DELA
449 DO J = 1,3
450 SFXION(J,IM) = FXION(J)
451 END DO
452 SVEL(IM) = VEL
453 SCP(IM) = QCP
454C MHP 02/12 COMMENTED CODE OUT, AS REPLICATED BELOW
455C IF(LSOUND) THEN
456C MHP 7/96 CALCULATION OF GAMMA1 FROM GUENTHER 1995 P.C.
457C CHRH = 1.0D0/QDP
458C CHT = -CHRH*QDT
459C CV = QCP - EXP(CLN*(HP(IM)-HD(IM)-HT(IM)))*CHT**2/CHRH
460C GAM1(IM) = CHRH*QCP/CV
461C PQDP(IM) = QDP
462C ENDIF
463
464C JVS 01/11 always want gamma:
465 CHRH = 1.0D0/QDP
466 CHT = -CHRH*QDT
467 CV = QCP - EXP(CLN*(HP(IM)-HD(IM)-HT(IM)))*CHT**2/CHRH
468 GAM1(IM) = CHRH*QCP/CV
469 PQDP(IM) = QDP
470 PQDT(IM) = QDT
471C JVS END
472
473
474 IF(LROT)THEN
475 SQOT(IM) = QOT
476C MHP 10/02 variable index error
477 IF(SESUM(IM).GT.0.0D0)THEN
478C IF(SESUM(I).GT.0.0D0)THEN
479C ETOT = SESUM(I)
480C EGNEUT = SEG(6,I)+SEG(7,I)
481 ETOT = SESUM(IM)
482 EGNEUT = SEG(6,IM)+SEG(7,IM)
483 FRACNUC(IM) = (ETOT - EGNEUT)/ETOT
484 ELSE
485 FRACNUC(IM) = 0.0D0
486 ENDIF
487 SQET(IM) = QET
488 ENDIF
489C DBG PULSE
490 IF (LPULSE) THEN
491 PQDP(IM) = QDP
492 PQED(IM) = QED
493 PQET(IM) = QET
494 PQOD(IM) = QOD
495 PQOT(IM) = QOT
496 PQCP(IM) = QCP
497 PRMU(IM) = RMU
498 PEMU(IM) = EMU
499 PQDT(IM) = QDT
500C 11/02/26 MHP via Claude
501C code changed to drop VALFMLT, VPHMLT and VCMXMLT, which only copied
502C TPGRAD's always-zero ALFMLT, PHMLT and CMXMLT. WRTMOD writes zeros.
503 END IF
504 30 30 CONTINUE
505
506 RETURN
507 END
1"""Python version of coefft.f (YREC 7be4133): the structure equations and
2their derivatives at every point, for the Henyey solution."""
3
4import math
5
6import numpy as np
7
8from pyrec import constants_mod
9from pyrec import debhu_mod
10from pyrec import dimensions_mod
11from pyrec import dpmix_mod
12from pyrec import fluxes_mod
13from pyrec import masschg2_mod
14from pyrec import nmlpar_mod
15from pyrec import pulse1_mod
16from pyrec import pulse2_mod
17from pyrec import rotder_mod
18from pyrec import roten_mod
19from pyrec import scrtch_mod
20from pyrec import sound_mod
21from pyrec.engeb import engeb
22from pyrec.eqstat import eqstat
23from pyrec.getopac import getopac
24from pyrec.reduce import reduce
25from pyrec.tpgrad import tpgrad
26
27JSON = dimensions_mod.json
28
29# COEFFT has SAVE (Fortran lines 138–146). The nuclear terms EG are set
30# only at points above TCUT(1), but read at every point not below it (SEG
31# with HT = TCUT(1) exactly), where they keep the values of the last point
32# that set them, in this call or an earlier one. Suspected bug (see the
33# page). QED and QET are zeroed at each point below the cutoff (since
34# 7be4133).
35eg = np.zeros(7)
36qed = 0.0
37qet = 0.0
38# ENGEB's per-point rates (local arrays in the Fortran, filled at IU).
39hr1, hr2, hr3, hr4, hr5, hr6, hr7, hr8, hr9, hr10, hr11, hr12, hr13, \
40 hf1, hf2 = (np.zeros(JSON + 1) for _ in range(15))
41
42
43def coefft(delts: float, m: int, hd: np.ndarray, hha: np.ndarray, hhb: np.ndarray, hhc: np.ndarray, hl: np.ndarray,
44 hmax: np.ndarray, hp: np.ndarray, hpp: np.ndarray, hr: np.ndarray, hs: np.ndarray, hs1: np.ndarray,
45 hs2: np.ndarray, ht: np.ndarray, htt: np.ndarray, hcomp: np.ndarray, lc: np.ndarray, tlumx: np.ndarray,
46 latmo: bool, lderiv: bool, lmix: bool, locond: bool, ksaha: int, fp: np.ndarray, ft: np.ndarray,
47 hkerot: np.ndarray, hkeroto: np.ndarray, jenv: int, teffl: float, cmixl: float) -> tuple[bool, bool, bool,
48 bool, int]:
49 """For each point: the equation of state, opacity, temperature gradient
50 and nuclear energy; the structure equations and their derivatives,
51 passed to REDUCE (the central conditions at point 1); the luminosity by
52 source; and per-point physics stored for output and other routines.
53
54 Translates: coefft.f#COEFFT (7be4133)
55
56 Arguments: delts, the time step (s); m, the number of points; the
57 model hd, hl, hp, hr, hs, ht (log rho, L/L_sun, log P, log r, log m,
58 log T), hs1, hs2 (the mass at each point and in each shell), htt, hpp
59 (the changes of log T, log P over the step), hcomp[species, point];
60 the matrices hha[k, l, point], hhb[k, point], hhc (the gravothermal
61 energy), hmax; lc (convective or not), tlumx[1..8] (the luminosity by
62 source); fp, ft, the rotational factors; hkerot, hkeroto, the
63 rotational kinetic energies; jenv; teffl; cmixl, the mixing length.
64 Arrays have index 0 unused and are changed in place.
65
66 Returns (latmo, lderiv, lmix, locond, ksaha): the flags set here and
67 the EOS's KSAHA.
68
69 """
70
71 global qed, qet
72 c = constants_mod
73 nml = nmlpar_mod
74 s = scrtch_mod
75 fxion = np.zeros(4)
76 # The previous point's equations, for REDUCE (set at point 1 first).
77 qp0 = qpr0 = qpp0 = qt0 = qtr0 = qtl0 = qtp0 = qtt0 = 0.0
78 qr0 = qrr0 = qrp0 = qrt0 = ql0 = qlp0 = qlt0 = 0.0
79 # QDT and QDP are locals (since 7be4133); EQSTAT sets them at each point.
80 qdt = qdp = 0.0
81
82 # Zero the solar neutrino fluxes (Fortran lines 148–155).
83 if nml.lsnu:
84 for j in range(1, 11):
85 fluxes_mod.fluxtot[j] = 0.0
86
87 # The flags, and the time step's inverse (Fortran lines 156–170).
88 locond = True
89 lderiv = True
90 latmo = False
91 lmix = False
92 lntrpy = delts > 0.0
93 if lntrpy:
94 deltsi = 1.0 / delts
95 time = 3.1558e7
96 timei = 3.1688e-8
97
98 # Fortran lines 171–173.
99 for j in range(1, 9):
100 tlumx[j] = 0.0
101
102 for im in range(1, m + 1): # label 30
103 # Local variables for the physics routines (Fortran lines 175–204).
104 thl = 0.0
105 sl = hs[im]
106 tl = ht[im]
107 pl = hp[im]
108 rl = hr[im]
109 b = hl[im]
110 x = hcomp[1, im]
111 y = hcomp[2, im]
112 z = hcomp[3, im]
113 xhe3 = hcomp[4, im]
114 xc12 = hcomp[5, im]
115 xc13 = hcomp[6, im]
116 xn14 = hcomp[7, im]
117 xo16 = hcomp[9, im]
118 xo18 = hcomp[11, im]
119 xh2 = hcomp[12, im]
120 iu = im
121 dl = hd[im]
122 fpl = fp[im]
123 ftl = ft[im]
124
125 # Debye-Hueckel composition (Fortran lines 205–214).
126 if nml.ldh:
127 debhu_mod.xxdh = hcomp[1, im]
128 debhu_mod.yydh = hcomp[2, im] + hcomp[4, im]
129 debhu_mod.zzdh = hcomp[3, im]
130 debhu_mod.zdh[1] = hcomp[5, im] + hcomp[6, im]
131 debhu_mod.zdh[2] = hcomp[7, im] + hcomp[8, im]
132 debhu_mod.zdh[3] = hcomp[9, im] + hcomp[10, im] + hcomp[11, im]
133
134 # The equation of state, the opacity and the gradient (Fortran lines
135 # 215–224).
136 (t, p, dl, d, beta, betai, beta14, rmu, amu, emu, eta, qdt, qdp,
137 qcp, dela, qdtt, qdtp, qat, qap, qcpt, qcpp, ksaha) = eqstat(
138 tl, 0.0, pl, 0.0, dl, 0.0, x, z, 0.0, 0.0, 0.0, fxion, 0.0, 0.0,
139 0.0, 0.0, qdt, qdp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
140 lderiv, latmo, ksaha)
141 o, ol, qod, qot = getopac(dl, tl, x, z, 0.0, 0.0, 0.0, 0.0, fxion)
142 dpmix_mod.iovim = im
143 (dele, delr, qact, qacp, qacr, vel, lconv) = tpgrad(
144 tl, t, pl, p, d, rl, sl, b, o, qdt, qdp, qot, qod, qcp, 0.0,
145 0.0, dela, qdtt, qdtp, qat, qap, 0.0, 0.0, 0.0, qcpt, qcpp,
146 0.0, lderiv, False, fpl, ftl, teffl, cmixl)
147 hd[im] = dl
148
149 # The structure equations (d/d ln m) and their derivatives (Fortran
150 # lines 225–271).
151 qtemp = c.c4pil + rl + rl + rl
152 qr = math.exp(c.cln * (sl - dl - qtemp))
153 qrr = -qr - qr - qr
154 qrp = -qr * qdp
155 qrt = -qr * qdt
156 # Question (see the page): f_P and f_T held constant in the
157 # derivatives (QFPR, QFTR omitted); f_T enters through TPGRAD.
158 qp = -math.exp(c.cln * (c.cgl + sl + sl - pl - qtemp - rl)) * fp[im]
159 qpr = -qp - qp - qp - qp
160 qpp = -qp
161 lc[im] = lconv
162 qt = dele * qp
163 qtr = -qt - qt - qt - qt
164 if not lconv:
165 qtl = c.clni * qt / b
166 qtp = qt * qod * qdp
167 qtt = qt * (-4.0 + qot + qod * qdt)
168 else:
169 qtl = 0.0
170 qtp = qt * (-1.0 + qacp)
171 qtt = qt * qact
172 qtr = qtr + qt * qacr
173 # QP, QT and QTL are members of PULSE2_MOD in the Fortran, so COEFFT
174 # overwrites the envelope's values there (see pulse2_mod's page).
175 pulse2_mod.qp = qp
176 pulse2_mod.qt = qt
177 pulse2_mod.qtl = qtl
178
179 # The luminosity equation, and the epsilon derivatives zero below the
180 # burning cutoff (Fortran lines 272–280).
181 ql = 0.0
182 qlt = 0.0
183 qlp = 0.0
184 qed = 0.0
185 qet = 0.0
186
187 # Nuclear energy above TCUT(1) (Fortran lines 281–320).
188 if tl > nml.tcut[1]:
189 (egg11, egg22, egg33, egg44, egg55, qed, qet, sum1, be7mfloc,
190 ealpca, enu) = engeb(
191 0.0, 0.0, 0.0, 0.0, 0.0, qed, qet, 0.0, dl, tl, x, y, xhe3,
192 xc12, xc13, xn14, xo16, xo18, xh2, iu, hr1, hr2, hr3, hr4,
193 hr5, hr6, hr7, hr8, hr9, hr10, hr11, hr12, hr13, hf1, hf2,
194 0.0, 0.0, 0.0)
195 e = sum1
196 eg[1] = egg11
197 eg[2] = egg22
198 eg[3] = egg33
199 eg[4] = egg44
200 eg[5] = egg55
201 eg[6] = enu
202 eca = ealpca
203 if nml.lsnu:
204 for j in range(1, 11):
205 fluxes_mod.fluxtot[j] += fluxes_mod.flux[j] * hs2[im]
206 for j in range(1, 7): # label 20
207 tlumx[j] = tlumx[j] + (hs2[im] / c.clsun) * eg[j]
208 thl = thl + (hs2[im] / c.clsun) * eg[j]
209 tlumx[8] = tlumx[8] + (hs2[im] / c.clsun) * eca
210 thl = thl + (hs2[im] / c.clsun) * eca
211 ql = e
212 qlt = qlt + qet + qed * qdt
213 qlp = qlp + qed * qdp
214
215 # Gravothermal energy (Fortran lines 321–368).
216 if lntrpy:
217 dt = deltsi
218 # Accretion: points at and above JENV add DLOGT, DLOGP.
219 # Question (see the page): accretion entropy.
220 if nml.lmdot and nml.dmdt0 > 0.0:
221 if im >= jenv:
222 httt = htt[im] + masschg2_mod.dlogt
223 hppp = hpp[im] + masschg2_mod.dlogp
224 else:
225 httt = htt[im]
226 hppp = hpp[im]
227 else:
228 httt = htt[im]
229 hppp = hpp[im]
230 # Question (see the page): a one-year floor, hard-coded.
231 if hcomp[1, im] > 0.01 and delts < time:
232 dt = timei
233 entr1 = p * qdt / d
234 entr2 = entr1 / dela
235 entr = (entr2 * httt - entr1 * hppp) * c.cln
236 entr3 = entr2 * c.cln * httt
237 egrav = dt * entr
238 hhc[im] = egrav
239 tlumx[7] = tlumx[7] + (hs2[im] / c.clsun) * egrav
240 ql = ql + egrav
241 # ENTR carries the factor QDT, so its log partials need
242 # QDTP/QDT and QDTT/QDT (since 7be4133).
243 qlp = qlp + dt * (entr * (1.0 - qdp + qdtp / qdt) - entr1
244 - entr3 * qap)
245 qlt = qlt + dt * (entr * (-qdt + qdtt / qdt) + entr2
246 - entr3 * qat)
247 if nml.lrot:
248 roten_mod.derot[im] = (dt * (hkerot[im] - hkeroto[im])
249 / hs2[im])
250 ql = ql - roten_mod.derot[im]
251
252 # Fortran lines 369–372.
253 cccql = c.clnsun * hs1[im]
254 ql = cccql * ql
255 qlp = cccql * qlp
256 qlt = cccql * qlt
257
258 # REDUCE for each pair of points; the central conditions at 1
259 # (Fortran lines 373–387).
260 if im > 1:
261 im1 = im
262 reduce(im1, hha, hhb, hl, hmax, hp, hr, hs, ht, qp0, qp, qpr0,
263 qpr, qpp0, qpp, qt0, qt, qtr0, qtr, qtl0, qtl, qtp0, qtp,
264 qtt0, qtt, qr0, qr, qrr0, qrr, qrp0, qrp, qrt0, qrt, ql0,
265 ql, qlp0, qlp, qlt0, qlt)
266 else:
267 hha[3, 1, 1] = c.cc13 * qdp
268 hha[3, 2, 1] = c.cc13 * qdt
269 hhb[3, 1] = -c.cc13 * (c.c4pi3l + dl - sl) - rl
270 hha[4, 1, 1] = -qlp
271 hha[4, 2, 1] = -qlt
272 hhb[4, 1] = c.clni * ql - b
273
274 # This point's equations, for the next (Fortran lines 388–402).
275 qp0 = qp
276 qpr0 = qpr
277 qpp0 = qpp
278 qt0 = qt
279 qtr0 = qtr
280 qtl0 = qtl
281 qtp0 = qtp
282 qtt0 = qtt
283 qr0 = qr
284 qrr0 = qrr
285 qrp0 = qrp
286 qrt0 = qrt
287 ql0 = ql
288 qlp0 = qlp
289 qlt0 = qlt
290
291 # Per-point physics for output and other routines (Fortran lines
292 # 403–453).
293 s.svel[im] = vel
294 # Suspected bug (see the page): EG is stale at HT = TCUT(1) exactly.
295 if ht[im] < nml.tcut[1]:
296 s.sesum[im] = 0.0
297 s.seg[7, im] = hhc[im]
298 for j in range(1, 7):
299 s.seg[j, im] = 0.0
300 else:
301 s.sesum[im] = eg[1] + eg[2] + eg[3] + eg[4] + eg[5]
302 s.seg[6, im] = eg[6]
303 s.seg[7, im] = hhc[im]
304 if s.sesum[im] > 1.0e-22:
305 esumi = 1.0 / s.sesum[im]
306 else:
307 esumi = 0.0
308 for j in range(1, 6):
309 s.seg[j, im] = eg[j] * esumi
310 s.sbeta[im] = beta
311 s.seta[im] = eta
312 s.locons[im] = locond
313 s.so[im] = o
314 s.sdel[1, im] = delr
315 s.sdel[2, im] = dele
316 s.sdel[3, im] = dela
317 for j in range(1, 4):
318 s.sfxion[j, im] = fxion[j]
319 s.svel[im] = vel
320 s.scp[im] = qcp
321
322 # Gamma_1, always (for the sound speed and pulsation output) (JVS
323 # 01/11) (Fortran lines 454–471).
324 chrh = 1.0 / qdp
325 cht = -chrh * qdt
326 cv = qcp - math.exp(c.cln * (hp[im] - hd[im] - ht[im])) * cht**2 / chrh
327 sound_mod.gam1[im] = chrh * qcp / cv
328 pulse1_mod.pqdp[im] = qdp
329 pulse1_mod.pqdt[im] = qdt
330
331 # With rotation (Fortran lines 474–488).
332 if nml.lrot:
333 rotder_mod.sqot[im] = qot
334 if s.sesum[im] > 0.0:
335 etot = s.sesum[im]
336 egneut = s.seg[6, im] + s.seg[7, im]
337 rotder_mod.fracnuc[im] = (etot - egneut) / etot
338 else:
339 rotder_mod.fracnuc[im] = 0.0
340 rotder_mod.sqet[im] = qet
341
342 # For the pulsation output (Fortran lines 489–503).
343 if nml.lpulse:
344 p1 = pulse1_mod
345 p1.pqdp[im] = qdp
346 p1.pqed[im] = qed
347 p1.pqet[im] = qet
348 p1.pqod[im] = qod
349 p1.pqot[im] = qot
350 p1.pqcp[im] = qcp
351 p1.prmu[im] = rmu
352 p1.pemu[im] = emu
353 p1.pqdt[im] = qdt
354 return latmo, lderiv, lmix, locond, ksaha