1C $$$$$$
2 SUBROUTINE MIXGRID(COD2,HD,HL,HP,HR,HS,HS1,HS2,
3 * * HSTOT,IBEG,IEND,LCZ,M,
4 * * ECOD2,EM,LDUM2)
5C 10/15/26 MHP via Claude
6C code changed to take JSON from DIMENSIONS_MOD instead of declaring
7C PARAMETER(JSON=5000) here.
8 USE DIMENSIONS_MOD
9C 10/14/26 MHP via Claude
10C code changed to convert COMMON/SPLIN/ into SPLIN_MOD.
11 USE SPLIN_MOD
12C 10/14/26 MHP via Claude
13C code changed to convert COMMON/MDPHY/ into MDPHY_MOD.
14 USE MDPHY_MOD
15C 10/14/26 MHP via Claude
16C code changed to convert COMMON/EGRID/ into EGRID_MOD.
17 USE EGRID_MOD
18C 10/14/26 MHP via Claude
19C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
20 USE NMLPAR_MOD
21C 10/14/26 MHP via Claude
22C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
23 USE CONSTANTS_MOD
24C 10/20/26 MHP via Claude
25C code changed to replace implicit typing with IMPLICIT NONE and
26C explicit declarations.
27 IMPLICIT NONE
28 REAL*8 COD2,DL,DM,DP,ECOD2,EM,EMBOT,EMTOP,FAC,HD,HL,HP,HR,HS,HS1,
29 * * HS2,HSTOT,QCHIR
30 INTEGER I,I0,I1,IBEG,IEND,II,M,NTAB,NTABB
31 LOGICAL*4 LCZ,LDUM2
32C 9/25/26 MHP via Claude
33C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
34C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
35C 10/12/26 MHP via Claude
36C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
37C namelist variables that the physics routines read from 27 COMMON
38C blocks which also held derived or working members. Those blocks keep
39C only their non-namelist members; five of them -- NEWMX, VMULT,
40C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
41C Derivation-only namelist variables from the same blocks went to
42C COMMON/NMLBYPASS/ instead, not here.
43C
44C Declared identically in all 121 files that hold any of these members.
45C Generated from one member list, so every copy is byte-identical; the
46C linker's 'size of symbol changed' warning is the check that they are.
47C 10/13/26 MHP via Claude: removed the unused COMMON/CTOL/ declaration
48C (no member referenced here; residue of the obsolete-option removals).
49C INPUT VARIABLES
50 DIMENSION HD(JSON),HL(JSON),HP(JSON),
51 * * HR(JSON),HS(JSON),HS1(JSON),HS2(JSON),
52 * * LCZ(JSON),COD2(JSON)
53C OUTPUT VARIABLES
54 DIMENSION ECOD2(JSON),EM(JSON)
55 SAVE
56C FLAG THE SPECIAL CASE OF A SINGLE UNSTABLE INTERFACE AND EXIT
57 IF(IEND-IBEG.LE.1)THEN
58 LDUM2 = .TRUE.
59 GOTO 9999
60 ELSE
61 LDUM2 = .FALSE.
62 ENDIF
63C DEFINE A GRID OF EQUALLY SPACED POINTS.
64 CALL GETGRID(HL,HP,HS,IBEG,IEND,M)
65C GETGRID HAS DEFINED A SET OF CO-ORDINATES (CHI) AND EQUALLY SPACED
66C MASS POINTS. NOW FIND THE OTHER QUANTITIES OF INTEREST AT ZONE
67C CENTERS:
68C TOTAL ZONE MASSES
69C INTERMEDIATE POINTS
70 DO I = 2, NTOT-1
71 EM(I) = 0.5D0*(ES1(I+1)-ES1(I-1))
72 END DO
73C SPECIAL TREATMENT OF THE BOUNDARIES; CAN BE CONVECTIVE.
74C IF CONVECTIVE SUM OVER ALL SHELLS. CARE IS NEEDED TO DO BOOK-KEEPING
75C PROPERLY AT THE EDGES - TOP IS HALFWAY TO EQUALLY SPACED POINT, NOT
76C HALFWAY TO EDGE OF UNEQUALLY SPACED ORIGINAL SET OF POINTS.
77C
78C CENTER
79 EMTOP = 0.5D0*(ES1(2)+ES1(1))
80 IF(IBEG.GT.1)THEN
81 EMBOT = 0.5D0*(HS1(IBEG)+HS1(IBEG-1))
82 ELSE
83 EMBOT = 0.0D0
84 ENDIF
85 EM(1) = EMTOP - EMBOT
86 IF(IBEG.GT.1)THEN
87 DO II = IBEG-1,1,-1
88 IF(.NOT.LCZ(II))THEN
89 I0 = I + 1
90 GOTO 10
91 ENDIF
92 EM(1) = EM(1)+HS2(II)
93 END DO
94 I0 = 1
95 10 10 CONTINUE
96 ELSE
97 I0 = 1
98 ENDIF
99C SURFACE
100 EMBOT = 0.5D0*(ES1(NTOT)+ES1(NTOT-1))
101 IF(IEND.LT.M)THEN
102 EMTOP = 0.5D0*(HS1(IEND)+HS1(IEND+1))
103 ELSE
104 EMTOP = EXP(CLN*HSTOT)
105 ENDIF
106 EM(NTOT) = EMTOP - EMBOT
107 IF(IEND.LT.M)THEN
108 DO II = IEND+1,M
109 IF(.NOT.LCZ(II))THEN
110 I1 = I -1
111 GOTO 20
112 ENDIF
113 EM(NTOT) = EM(NTOT)+HS2(II)
114 END DO
115 I1 = M
116 20 20 CONTINUE
117 ELSE
118 I1 = M
119 ENDIF
120C NOW SOLVE FOR QUANTITIES NEEDED AT THE ZONE EDGES. THESE ARE
121C RELATED TO THE DIFFUSION COEFFICIENTS. UNLIKE THE EQUALLY SPACED
122C GRID IN R, WE NEED TO INCLUDE A JACOBIAN TERM FOR THE TRANSFORMATION
123C OF VARIABLES.
124 NTAB = IEND - IBEG + 1
125 XTAB(1) = CHI(1)
126 DO I = 2,NTAB
127 XTAB(I) = 0.5D0*(CHI(I)+CHI(I-1))
128 END DO
129 NTABB = NTAB + 1
130 XTAB(NTABB) = CHI(NTAB)
131C DIFFUSION COEFFICIENT FOR MIXING - ASSUME CONSTANT BELOW
132C BOTTOM INTERFACE OR ABOVE TOP INTERFACE
133 YTAB(1) = COD2(IBEG+1)
134 DO I = 2,NTAB
135 II = IBEG + I - 1
136 YTAB(I) = COD2(II)
137 END DO
138 YTAB(NTABB) = COD2(IEND)
139 XVAL(1) = CHI(1)
140 DO I = 2, NTOT
141 XVAL(I) = ECHI(I)-0.5D0*DCHI
142 END DO
143 CALL OSPLIN(XVAL,ECOD2,XTAB,YTAB,NTABB,NTOT)
144C PRODUCT OF RHO R^2 BY D CHI/DR
145 DM = HPTTOL(2)
146 DL = HPTTOL(9)*HL(M)*CLSUN
147 DP = HPTTOL(11)
148 DO I = 1, NTAB
149 II = IBEG + I - 1
150 XTAB(I) = CHI(I)
151C D CHI/DR = 1/DM*( D LOG M/DR) + 1/DL*(DL/DR) - 1/DP*(D LOG P/DR)
152C OR, USING FAC = 4*PI*RHO*R**2
153C D CHI/DR = FAC/(LN 10 * DM * M) + FAC*EPSILON/DL + RHO*GM/(LN10*DP*R**2)
154C STORED IN YVAL
155 FAC = C4PI*EXP(CLN*(HD(II)+2.0D0*HR(II)))
156 QCHIR = FAC/(CLN*DM*HS1(II))+FAC*EPSM(II)/DL+
157 * * EXP(CLN*(CGL+HD(II)+HS(II)-HP(II)-2.0D0*HR(II)))/(CLN*DP)
158 YTAB(I) = HD(II) + LOG10(QCHIR) + 2.0D0*HR(II)
159 END DO
160 CALL OSPLIN(XVAL,YVAL,XTAB,YTAB,NTAB,NTOT)
161C NOW ADD MULTIPLICATIVE FACTORS TO DIFFUSION COEFFICIENTS
162 DO I = 1, NTOT
163 ECOD2(I) = ECOD2(I)*EXP(CLN*YVAL(I))
164 END DO
165 9999 9999 CONTINUE
166 RETURN
167 END
1"""Python version of mixgrid.f (YREC 7be4133): the equally spaced grid in
2chi for mixing one unstable region, with its zone masses and coefficients,
3for MIXCOM."""
4
5import math
6
7import numpy as np
8
9from pyrec import constants_mod
10from pyrec import egrid_mod
11from pyrec import mdphy_mod
12from pyrec import nmlpar_mod
13from pyrec import splin_mod
14from pyrec.getgrid import getgrid
15from pyrec.osplin import osplin
16
17# The Fortran's locals (SAVE).
18i0 = 0
19i1 = 0
20
21
22def mixgrid(cod2: np.ndarray, hd: np.ndarray, hl: np.ndarray, hp: np.ndarray, hr: np.ndarray, hs: np.ndarray,
23 hs1: np.ndarray, hs2: np.ndarray, hstot: float, ibeg: int, iend: int, lcz: np.ndarray, m: int,
24 ecod2: np.ndarray, em: np.ndarray, ldum2: bool) -> bool:
25 """Set up the equal grid in chi over the region ibeg..iend (GETGRID),
26 the mass em of each grid zone (the end zones with any adjoining
27 convection zone), and the coefficient ecod2: cod2 interpolated to the
28 zone edges times rho r^2 dchi/dr. Does nothing but set ldum2 = True
29 when the region spans a single unstable interface.
30
31 Translates: mixgrid.f#MIXGRID (7be4133)
32
33 Arguments: the mixing coefficients cod2 at the model interfaces; the
34 model hd, hl, hp, hr, hs (logs), hs1 (mass, g), hs2 (shell masses),
35 hstot (log total mass); the region ibeg..iend; the flags lcz; m shells.
36 ldum2 is passed in with any value. Arrays have index 0 unused.
37
38 Sets in place: ecod2 and em on the egrid_mod.ntot grid points.
39
40 Returns ldum2.
41
42 """
43
44 global i0, i1
45 c = constants_mod
46 chi = egrid_mod.chi
47 echi = egrid_mod.echi
48 es1 = egrid_mod.es1
49 xval = splin_mod.xval
50 yval = splin_mod.yval
51 xtab = splin_mod.xtab
52 ytab = splin_mod.ytab
53
54 # The special case of a single unstable interface (Fortran lines
55 # 56–62).
56 if iend - ibeg <= 1:
57 ldum2 = True
58 return ldum2 # GOTO 9999
59 ldum2 = False
60
61 # The grid of equally spaced points (chi, echi, es1, dchi, ntot)
62 # (Fortran lines 63–64).
63 getgrid(hl, hp, hs, ibeg, iend, m)
64 ntot = egrid_mod.ntot
65 dchi = egrid_mod.dchi
66
67 # Zone masses, intermediate points (Fortran lines 65–72).
68 for i in range(2, ntot):
69 em[i] = 0.5 * (es1[i + 1] - es1[i - 1])
70 i = max(ntot, 2) # the Fortran's I after DO I = 2, NTOT-1
71
72 # The centre: halfway to the next grid point, plus any convection zone
73 # below (Fortran lines 73–98).
74 emtop = 0.5 * (es1[2] + es1[1])
75 if ibeg > 1:
76 embot = 0.5 * (hs1[ibeg] + hs1[ibeg - 1])
77 else:
78 embot = 0.0
79 em[1] = emtop - embot
80 if ibeg > 1:
81 for ii in range(ibeg - 1, 0, -1):
82 if not lcz[ii]:
83 # I, not II; i0 is unused?
84 i0 = i + 1
85 break # GOTO 10
86 em[1] = em[1] + hs2[ii]
87 else:
88 i0 = 1
89 else:
90 i0 = 1
91
92 # The surface (Fortran lines 99–119).
93 embot = 0.5 * (es1[ntot] + es1[ntot - 1])
94 if iend < m:
95 emtop = 0.5 * (hs1[iend] + hs1[iend + 1])
96 else:
97 emtop = math.exp(c.cln * hstot)
98 em[ntot] = emtop - embot
99 if iend < m:
100 for ii in range(iend + 1, m + 1):
101 if not lcz[ii]:
102 # I, not II; i1 is unused?
103 i1 = i - 1
104 break # GOTO 20
105 em[ntot] = em[ntot] + hs2[ii]
106 else:
107 i1 = m
108 else:
109 i1 = m
110
111 # The coefficient at the zone edges, constant beyond the end interfaces
112 # (Fortran lines 120–143).
113 ntab = iend - ibeg + 1
114 xtab[1] = chi[1]
115 for i in range(2, ntab + 1):
116 xtab[i] = 0.5 * (chi[i] + chi[i - 1])
117 ntabb = ntab + 1
118 xtab[ntabb] = chi[ntab]
119 ytab[1] = cod2[ibeg + 1]
120 for i in range(2, ntab + 1):
121 ii = ibeg + i - 1
122 ytab[i] = cod2[ii]
123 ytab[ntabb] = cod2[iend]
124 xval[1] = chi[1]
125 for i in range(2, ntot + 1):
126 xval[i] = echi[i] - 0.5 * dchi
127 osplin(xval, ecod2, xtab, ytab, ntabb, ntot)
128
129 # log10 of rho r^2 dchi/dr, with FAC = 4 pi rho r^2 (Fortran lines
130 # 144–160).
131 hpttol = nmlpar_mod.hpttol
132 dm = hpttol[2]
133 dl = hpttol[9] * hl[m] * c.clsun
134 dp = hpttol[11]
135 for i in range(1, ntab + 1):
136 ii = ibeg + i - 1
137 xtab[i] = chi[i]
138 fac = c.c4pi * math.exp(c.cln * (hd[ii] + 2.0 * hr[ii]))
139 # Question (see the page): the comment omits P in the last term.
140 qchir = (fac / (c.cln * dm * hs1[ii]) + fac * mdphy_mod.epsm[ii] / dl
141 + math.exp(c.cln * (c.cgl + hd[ii] + hs[ii] - hp[ii]
142 - 2.0 * hr[ii])) / (c.cln * dp))
143 ytab[i] = hd[ii] + math.log10(qchir) + 2.0 * hr[ii]
144 osplin(xval, yval, xtab, ytab, ntab, ntot)
145
146 # The multiplicative factors (Fortran lines 161–164).
147 for i in range(1, ntot + 1):
148 ecod2[i] = ecod2[i] * math.exp(c.cln * yval[i])
149
150 return ldum2