1C $$$$$$
2C SUBROUTINE MICRODIFF_MTE(NLIGHT,CSLIGHT,HCOMP,HQPR,HRU,HS1,HTU,IBEGIN,
3C * IEND,M,DR,NPT,LC,ODEN,OTEM,EM,ER,EDEN,ETEM,EHQPR,EDELR, # KC 2025-05-31
4 SUBROUTINE MICRODIFF_MTE(NLIGHT,CSLIGHT,HCOMP,HQPR,HRU,HS1,IBEGIN,
5 * * IEND,M,DR,NPT,ODEN,OTEM,EM,ER,EDEN,ETEM,EHQPR,EDELR,
6 * * EX,EY,EZ,ELI,EM_H,ER_H,EDEN_H,ETEM_H,EHQPR_H,EDELR_H,
7 * * EX_H,EY_H,EZ_H,ELI_H)
8C 10/15/26 MHP via Claude
9C code changed to take JSON from DIMENSIONS_MOD instead of declaring
10C PARAMETER(JSON=5000) here.
11 USE DIMENSIONS_MOD
12C 10/14/26 MHP via Claude
13C code changed to convert COMMON/SCRTCH/ into SCRTCH_MOD.
14 USE SCRTCH_MOD
15C 10/14/26 MHP via Claude
16C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
17 USE NMLPAR_MOD
18C 10/20/26 MHP via Claude
19C code changed to replace implicit typing with IMPLICIT NONE and
20C explicit declarations.
21 IMPLICIT NONE
22 REAL*8 DR,DRMIN,DRTOT,EDELR,EDELR_H,EDEN,EDEN_H,EHQPR,EHQPR_H,ELI,
23 * * ELI_H,EM,EM_H,ER,ER_H,ETEM,ETEM_H,EX,EX_H,EY,EY_H,EZ,EZ_H,
24 * * FACDERIV,FACINTERP,FX,GRIDRAD,HCOMP,HQPR,HRU,HS1,ODEN,OTEM,
25 * * TABLER
26 INTEGER I,IBEGIN,IEND,II,ISTART,IU,J,JMIN,K,K0,KK,M,NLIGHT,NPT
27
28C 10/12/26 MHP via Claude
29C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
30C namelist variables that the physics routines read from 27 COMMON
31C blocks which also held derived or working members. Those blocks keep
32C only their non-namelist members; five of them -- NEWMX, VMULT,
33C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
34C Derivation-only namelist variables from the same blocks went to
35C COMMON/NMLBYPASS/ instead, not here.
36C
37C Declared identically in all 121 files that hold any of these members.
38C Generated from one member list, so every copy is byte-identical; the
39C linker's 'size of symbol changed' warning is the check that they are.
40C DIMENSION HCOMP(15,JSON),HQPR(JSON),HRU(JSON),HS1(JSON),HTU(JSON), ! KC 2025-05-31
41 DIMENSION HCOMP(15,JSON),HQPR(JSON),HRU(JSON),HS1(JSON),
42 * * ODEN(JSON),OTEM(JSON),EM(JSON),ER(JSON),EDEN(JSON),ETEM(JSON),
43 * * EHQPR(JSON),EDELR(JSON),EX(JSON),EY(JSON),EZ(JSON),
44 * * ELI(NLIGHT,JSON),EM_H(JSON),ER_H(JSON),EDEN_H(JSON),
45 * * ETEM_H(JSON),EHQPR_H(JSON),EDELR_H(JSON),EX_H(JSON),
46C KC 2025-05-30 fixed -Wconversion
47C * EY_H(JSON),EZ_H(JSON),ELI_H(NLIGHT,JSON),CSLIGHT(NLIGHT),
48 * * EY_H(JSON),EZ_H(JSON),ELI_H(NLIGHT,JSON),
49 * * FACINTERP(4),FACDERIV(4),TABLER(4)
50 INTEGER CSLIGHT(NLIGHT)
51 INTEGER HALFJSON
52 SAVE
53C FIND MINIMUM MODEL POINT SPACING IN RADIUS.
54 DRTOT = HRU(IEND)-HRU(IBEGIN)
55 DRMIN = DRTOT
56c ID THE MINIMUM SPACING IN THE 20 LAYERS BELOW THE SURFACE CZ.
57 ISTART = MAX(IEND-20,IBEGIN+1)
58 DO 7 I = ISTART,IEND
59 DRMIN=MIN(DRMIN,HRU(I)-HRU(I-1))
60 7 7 CONTINUE
61C ASSIGN THE MINIMUM NUMBER OF EQUALLY SPACED GRID POINTS SUCH THAT
62C DR <= DRMIN.
63 NPT=INT(DRTOT/DRMIN)
64 IF(MOD(DRTOT,DRMIN).NE.0.0D0)NPT=NPT+1
65C JVS add additional trap to deal with models with NPT=1
66C 10/30/26 MHP via Claude
67C code changed to require at least 4 points, not 2. The 4-point
68C Lagrangian stencils here and on the way back read ER(K0..K0+3), so a
69C 2- or 3-point grid read points never set, or ER(-1) and ER(0).
70 NPT = MAX(NPT,4)
71C ENSURE THAT NUMBER OF POINTS DOES NOT EXCEED JSON.
72
73C 10/15/26 MHP via Claude
74C code changed to take this cap from JSON rather than repeating its
75C value. The name says half of JSON, but the value was 5000, which is
76C all of JSON -- presumably the cap was raised from JSON/2 to the full
77C array bound and the name was left behind. Hardcoding 5000 meant that
78C if JSON ever changed, this cap would silently stop matching the bound
79C it exists to enforce. The name is kept for now so this change stays
80C behaviour-neutral; see KNOWN_ISSUES.md issue 26.
81 HALFJSON = JSON
82 NPT=MIN(NPT,HALFJSON)
83 DR = DRTOT/DFLOAT(NPT-1)
84C SET UP VECTOR OF EQUALLY SPACED RADII AT ZONE MIDPOINTS.
85 ER_H(1)=HRU(IBEGIN)+0.5D0*DR
86C JVS added logic trap (IF statement)
87 IF (NPT .EQ. 2) THEN
88 ER_H(2)=ER_H(1)+DR
89 ELSE
90 DO 10 I = 2,NPT-1 ! old piece
91 IF(I-1 .EQ. 0) PRINT*, 'mte line 47'
92 ER_H(I)=ER_H(I-1)+DR ! old piece
93 10 10 CONTINUE ! old piece
94 ENDIF
95
96C NOW USE 4-POINT LAGRANGIAN INTERPOLATION TO FIND RUN OF VARIABLES
97C AT EQUALLY SPACED ZONE MIDPOINTS.
98C
99C FIRST POINT : LINEAR INTERPOLATION BETWEEN STARTING POINT AND 2ND PT.
100 DO 15 IU=2,NPT
101 IF(HRU(IU).GE.ER_H(1))GOTO 17
102 15 15 CONTINUE
103 IU=NPT
104 17 17 CONTINUE
105 FX=(ER_H(1)-HRU(IU-1))/(HRU(IU)-HRU(IU-1))
106 EM_H(1) = HS1(IU-1)+FX*(HS1(IU)-HS1(IU-1))
107 EDEN_H(1) = ODEN(IU-1)+FX*(ODEN(IU)-ODEN(IU-1))
108 ETEM_H(1) = OTEM(IU-1)+FX*(OTEM(IU)-OTEM(IU-1))
109 EHQPR_H(1) = HQPR(IU-1)+FX*(HQPR(IU)-HQPR(IU-1))
110 EDELR_H(1) = SDEL(2,IU-1)+FX*(SDEL(2,IU)-SDEL(2,IU-1))
111 EX_H(1) = HCOMP(1,IU-1)+FX*(HCOMP(1,IU)-HCOMP(1,IU-1))
112 EY_H(1) = HCOMP(2,IU-1)+FX*(HCOMP(2,IU)-HCOMP(2,IU-1))
113 EZ_H(1) = HCOMP(3,IU-1)+FX*(HCOMP(3,IU)-HCOMP(3,IU-1))
114 IF(LDIFLI)THEN
115 DO KK=1,NLIGHT
116 II = CSLIGHT(KK)
117 ELI_H(KK,1) = HCOMP(II,IU-1)+FX*(HCOMP(II,IU)-HCOMP(II,IU-1))
118 END DO
119 ENDIF
120
121C FOR OTHER POINTS: FIRST FIND 4 NEAREST (IN RADIUS) MODEL POINTS
122C AND THEN FIND LAGRANGIAN INTERPOLATION FACTORS. APPLY THEM TO FIND
123C MODEL QUANTITIES AT THE EQUALLY SPACED GRID POINTS.
124C JMIN IS THE UPPERMOST MODEL POINT ABOVE THE PREVIOUS EQUALLY SPACED
125C GRID POINT (IN RADIUS).
126 JMIN=IBEGIN+1
127 DO 50 I=2,NPT-1
128 DO 20 J = JMIN,IEND
129C FIND 4 MODEL POINTS CLOSEST TO THE EQUALLY SPACED GRID POINT.
130 IF(HRU(J).GE.ER_H(I))THEN
131C ENSURE THAT FIRST INTERPOLATION POINT NO LESS THAN FIRST MODEL POINT.
132 K0 = MAX(J-2,1)
133C ENSURE THAT LAST INTERPOLATION POINT NO GREATER THAN LAST MODEL POINT.
134 K0 = MIN(K0,M-3)
135 JMIN=J
136 GOTO 30
137 ENDIF
138 20 20 CONTINUE
139 K0 = M-3
140 JMIN=M
141 30 30 CONTINUE
142 DO 40 K=1,4
143 TABLER(K)=HRU(K0+K-1)
144 40 40 CONTINUE
145 GRIDRAD=ER_H(I)
146C FIND 4 POINT LAGRANGIAN INTERPOLATION FACTORS.
147C FACINTERP=INTERPOLATION FACTORS FOR POINT GRIDRAD GIVEN THE 4 TABLE
148C RADII IN TABLER; FACDERIV=SAME FOR DERIVATIVES AT POINT GRIDRAD.
149 CALL INTERP(TABLER,FACINTERP,FACDERIV,GRIDRAD)
150C PERFORM 4 POINT LAGRANGIAN INTERPOLATION FOR DESIRED QUANTITIES:
151C MASS WITHIN THE RADIUS ER
152 EM_H(I) = FACINTERP(1)*HS1(K0)+FACINTERP(2)*HS1(K0+1)+
153 * * FACINTERP(3)*HS1(K0+2)+FACINTERP(4)*HS1(K0+3)
154C RELAVENT PHYSICAL VARIABLES
155 EDEN_H(I) = FACINTERP(1)*ODEN(K0)+FACINTERP(2)*ODEN(K0+1)+
156 * * FACINTERP(3)*ODEN(K0+2)+FACINTERP(4)*ODEN(K0+3)
157 ETEM_H(I) = FACINTERP(1)*OTEM(K0)+FACINTERP(2)*OTEM(K0+1)+
158 * * FACINTERP(3)*OTEM(K0+2)+FACINTERP(4)*OTEM(K0+3)
159 EHQPR_H(I) = FACINTERP(1)*HQPR(K0)+FACINTERP(2)*HQPR(K0+1)+
160 * * FACINTERP(3)*HQPR(K0+2)+FACINTERP(4)*HQPR(K0+3)
161 EDELR_H(I) = FACINTERP(1)*SDEL(2,K0)+FACINTERP(2)*SDEL(2,K0+1)+
162 * * FACINTERP(3)*SDEL(2,K0+2)+FACINTERP(4)*SDEL(2,K0+3)
163C MASS FRACTION OF HYDROGEN
164 EX_H(I)=FACINTERP(1)*HCOMP(1,K0)
165 * * +FACINTERP(2)*HCOMP(1,K0+1)
166 * * +FACINTERP(3)*HCOMP(1,K0+2)
167 * * +FACINTERP(4)*HCOMP(1,K0+3)
168C MASS FRACTION OF HELIUM
169 EY_H(I)=FACINTERP(1)*HCOMP(2,K0)
170 * * +FACINTERP(2)*HCOMP(2,K0+1)
171 * * +FACINTERP(3)*HCOMP(2,K0+2)
172 * * +FACINTERP(4)*HCOMP(2,K0+3)
173C MASS FRACTION OF METALS
174 EZ_H(I)=FACINTERP(1)*HCOMP(3,K0)
175 * * +FACINTERP(2)*HCOMP(3,K0+1)
176 * * +FACINTERP(3)*HCOMP(3,K0+2)
177 * * +FACINTERP(4)*HCOMP(3,K0+3)
178C MASS FRACTION OF LIGHT ELEMENTS
179 IF(LDIFLI)THEN
180 DO KK=1,NLIGHT
181 II = CSLIGHT(KK)
182 ELI_H(KK,I)=FACINTERP(1)*HCOMP(II,K0)
183 * * +FACINTERP(2)*HCOMP(II,K0+1)
184 * * +FACINTERP(3)*HCOMP(II,K0+2)
185 * * +FACINTERP(4)*HCOMP(II,K0+3)
186 END DO
187 ENDIF
188 50 50 CONTINUE
189
190C SET UP VECTOR OF EQUALLY SPACED RADII AT ZONE CENTERS.
191 ER(1)=HRU(IBEGIN)
192 DO 60 I = 2,NPT
193 ER(I)=ER(I-1)+DR
194 60 60 CONTINUE
195
196C NOW USE 4-POINT LAGRANGIAN INTERPOLATION TO FIND RUN OF VARIABLES
197C AT EQUALLY SPACED ZONE CENTERS.
198C
199C FIRST POINT : BY DEFINITION, AT STARTING POINT.
200C G Somers; added interpolation for Xfrac, Rho, T, and HQPR.
201 EM(1) = HS1(IBEGIN)
202 EDEN(1) = ODEN(IBEGIN)
203 ETEM(1) = OTEM(IBEGIN)
204 EHQPR(1) = HQPR(IBEGIN)
205 EDELR(1) = SDEL(2,IBEGIN)
206 EX(1) = HCOMP(1,IBEGIN)
207 EY(1) = HCOMP(2,IBEGIN)
208 EZ(1) = HCOMP(3,IBEGIN)
209 IF(LDIFLI)THEN
210 DO KK=1,NLIGHT
211 II = CSLIGHT(KK)
212 ELI(KK,1) = HCOMP(II,IBEGIN)
213 END DO
214 ENDIF
215C FOR OTHER POINTS: FIRST FIND 4 NEAREST (IN RADIUS) MODEL POINTS
216C AND THEN FIND LAGRANGIAN INTERPOLATION FACTORS. APPLY THEM TO FIND
217C MODEL QUANTITIES AT THE EQUALLY SPACED GRID POINTS.
218C JMIN IS THE UPPERMOST MODEL POINT ABOVE THE PREVIOUS EQUALLY SPACED
219C GRID POINT (IN RADIUS).
220 JMIN=IBEGIN+1
221 DO 70 I=2,NPT-1
222 DO 80 J = JMIN,IEND
223C FIND 4 MODEL POINTS CLOSEST TO THE EQUALLY SPACED GRID POINT.
224 IF(HRU(J).GE.ER(I))THEN
225C ENSURE THAT FIRST INTERPOLATION POINT NO LESS THAN FIRST MODEL POINT.
226 K0 = MAX(J-2,1)
227C ENSURE THAT LAST INTERPOLATION POINT NO GREATER THAN LAST MODEL POINT.
228 K0 = MIN(K0,M-3)
229 JMIN=J
230 GOTO 90
231 ENDIF
232 80 80 CONTINUE
233 K0 = M-3
234 JMIN=M
235 90 90 CONTINUE
236 DO 100 K=1,4
237 TABLER(K)=HRU(K0+K-1)
238 100 100 CONTINUE
239 GRIDRAD=ER(I)
240C FIND 4 POINT LAGRANGIAN INTERPOLATION FACTORS.
241C FACINTERP=INTERPOLATION FACTORS FOR POINT GRIDRAD GIVEN THE 4 TABLE
242C RADII IN TABLER; FACDERIV=SAME FOR DERIVATIVES AT POINT GRIDRAD.
243 CALL INTERP(TABLER,FACINTERP,FACDERIV,GRIDRAD)
244C PERFORM 4 POINT LAGRANGIAN INTERPOLATION FOR DESIRED QUANTITIES:
245C MASS WITHIN THE RADIUS ER
246 EM(I) = FACINTERP(1)*HS1(K0)+FACINTERP(2)*HS1(K0+1)+
247 * * FACINTERP(3)*HS1(K0+2)+FACINTERP(4)*HS1(K0+3)
248 EDEN(I) = FACINTERP(1)*ODEN(K0)+FACINTERP(2)*ODEN(K0+1)+
249 * * FACINTERP(3)*ODEN(K0+2)+FACINTERP(4)*ODEN(K0+3)
250 ETEM(I) = FACINTERP(1)*OTEM(K0)+FACINTERP(2)*OTEM(K0+1)+
251 * * FACINTERP(3)*OTEM(K0+2)+FACINTERP(4)*OTEM(K0+3)
252 EHQPR(I) = FACINTERP(1)*HQPR(K0)+FACINTERP(2)*HQPR(K0+1)+
253 * * FACINTERP(3)*HQPR(K0+2)+FACINTERP(4)*HQPR(K0+3)
254 EDELR(I) = FACINTERP(1)*SDEL(2,K0)+FACINTERP(2)*SDEL(2,K0+1)+
255 * * FACINTERP(3)*SDEL(2,K0+2)+FACINTERP(4)*SDEL(2,K0+3)
256 EX(I)=FACINTERP(1)*HCOMP(1,K0)
257 * * +FACINTERP(2)*HCOMP(1,K0+1)
258 * * +FACINTERP(3)*HCOMP(1,K0+2)
259 * * +FACINTERP(4)*HCOMP(1,K0+3)
260 EY(I)=FACINTERP(1)*HCOMP(2,K0)
261 * * +FACINTERP(2)*HCOMP(2,K0+1)
262 * * +FACINTERP(3)*HCOMP(2,K0+2)
263 * * +FACINTERP(4)*HCOMP(2,K0+3)
264 EZ(I)=FACINTERP(1)*HCOMP(3,K0)
265 * * +FACINTERP(2)*HCOMP(3,K0+1)
266 * * +FACINTERP(3)*HCOMP(3,K0+2)
267 * * +FACINTERP(4)*HCOMP(3,K0+3)
268 IF(LDIFLI)THEN
269 DO KK=1,NLIGHT
270 II = CSLIGHT(KK)
271 ELI(KK,I)=FACINTERP(1)*HCOMP(II,K0)
272 * * +FACINTERP(2)*HCOMP(II,K0+1)
273 * * +FACINTERP(3)*HCOMP(II,K0+2)
274 * * +FACINTERP(4)*HCOMP(II,K0+3)
275 END DO
276 ENDIF
277 70 70 CONTINUE
278C LAST POINT : BY DEFINITION, AT ENDING POINT.
279 EM(NPT) = HS1(IEND)
280 EDEN(NPT) = ODEN(IEND)
281 ETEM(NPT) = OTEM(IEND)
282 EHQPR(NPT) = HQPR(IEND)
283 EDELR(NPT) = SDEL(2,IEND)
284 EX(NPT) = HCOMP(1,IEND)
285 EY(NPT) = HCOMP(2,IEND)
286 EZ(NPT) = HCOMP(3,IEND)
287 IF(LDIFLI)THEN
288 DO KK=1,NLIGHT
289 II = CSLIGHT(KK)
290 ELI(KK,NPT) = HCOMP(II,IEND)
291 END DO
292 ENDIF
293 RETURN
294 END
1"""Python version of microdiff_mte.f (YREC 7be4133): "model to equal",
2the model interpolated onto an equally spaced grid in radius."""
3
4import math
5
6import numpy as np
7
8from pyrec import dimensions_mod
9from pyrec import nmlpar_mod
10from pyrec import scrtch_mod
11from pyrec.interp import interp
12
13JSON = dimensions_mod.json
14
15# The Fortran's local arrays (SAVE).
16facinterp = np.zeros(5)
17facderiv = np.zeros(5)
18tabler = np.zeros(5)
19
20
21def _lagrange(f, k0):
22 # FACINTERP(1)*F(K0) + ... + FACINTERP(4)*F(K0+3), in the Fortran's
23 # order (Fortran lines 152–187, 246–275).
24 return (facinterp[1] * f[k0] + facinterp[2] * f[k0 + 1]
25 + facinterp[3] * f[k0 + 2] + facinterp[4] * f[k0 + 3])
26
27
28def _find_k0(r, jmin, iend, m, hru):
29 # Labels 20/30 (and 80/90): the first model point J >= JMIN at or above
30 # radius r gives the four interpolation points K0..K0+3, kept inside
31 # 1..M; returns (k0, jmin) (Fortran lines 128–141, 222–235).
32 for j in range(jmin, iend + 1):
33 if hru[j] >= r:
34 k0 = max(j - 2, 1)
35 k0 = min(k0, m - 3)
36 return k0, j
37 return m - 3, m
38
39
40def microdiff_mte(nlight: int, cslight: np.ndarray, hcomp: np.ndarray, hqpr: np.ndarray, hru: np.ndarray,
41 hs1: np.ndarray, ibegin: int, iend: int, m: int, dr: float, npt: int, oden: np.ndarray,
42 otem: np.ndarray, em: np.ndarray, er: np.ndarray, eden: np.ndarray, etem: np.ndarray,
43 ehqpr: np.ndarray, edelr: np.ndarray, ex: np.ndarray, ey: np.ndarray, ez: np.ndarray, eli: np.ndarray,
44 em_h: np.ndarray, er_h: np.ndarray, eden_h: np.ndarray, etem_h: np.ndarray, ehqpr_h: np.ndarray,
45 edelr_h: np.ndarray, ex_h: np.ndarray, ey_h: np.ndarray, ez_h: np.ndarray,
46 eli_h: np.ndarray) -> tuple[float, int]:
47 """Interpolate the model between shells ibegin and iend onto an equally
48 spaced grid in radius, at the grid points (e...) and the midpoints
49 between them (e..._h), for MICRODIFF.
50
51 Translates: microdiff_mte.f#MICRODIFF_MTE (7be4133)
52
53 Arguments: nlight light elements, at the hcomp rows cslight[1..nlight];
54 the model's hcomp[k, j], hqpr, radius hru (Rsun), mass hs1, density
55 oden and temperature otem, with m shells; the gradient comes from
56 scrtch_mod.sdel[2, j]. dr and npt are passed in with any value.
57 Arrays have index 0 unused.
58
59 Sets in place: em, er, eden, etem, ehqpr, edelr, ex, ey, ez, eli[kk, i]
60 on the npt grid points, and the same with _h on the npt - 1 midpoints.
61
62 Returns (dr, npt): the grid spacing and the number of grid points.
63
64 """
65
66 sdel = scrtch_mod.sdel
67 ldifli = nmlpar_mod.ldifli
68
69 # Find the minimum model point spacing in radius, in the 20 layers below
70 # the surface convection zone (Fortran lines 53–60).
71 # Question (see the page): only these 20 layers.
72 drtot = hru[iend] - hru[ibegin]
73 drmin = drtot
74 istart = max(iend - 20, ibegin + 1)
75 for i in range(istart, iend + 1):
76 drmin = min(drmin, hru[i] - hru[i - 1])
77
78 # The minimum number of equally spaced points such that DR <= DRMIN
79 # (Fortran lines 61–64).
80 # Question (see the page): NPT points make NPT - 1 intervals.
81 npt = int(drtot / drmin)
82 if math.fmod(drtot, drmin) != 0.0:
83 npt = npt + 1
84
85 # At least 4 points, as the 4-point Lagrangian stencils read
86 # ER(K0..K0+3), and at most JSON; the spacing (Fortran lines 65–83).
87 npt = max(npt, 4)
88 halfjson = JSON
89 npt = min(npt, halfjson)
90 dr = drtot / float(npt - 1)
91
92 # Equally spaced radii at the zone midpoints (Fortran lines 84–94); the
93 # NPT = 2 branch and the debug PRINT cannot run.
94 er_h[1] = hru[ibegin] + 0.5 * dr
95 if npt == 2:
96 er_h[2] = er_h[1] + dr
97 else:
98 for i in range(2, npt): # DO 10
99 er_h[i] = er_h[i - 1] + dr
100
101 # First midpoint: linear interpolation (Fortran lines 96–119).
102 # Suspected bug (see the page): the search runs over model indices
103 # 2..NPT, not IBEGIN+1..IEND.
104 iu = npt
105 for k in range(2, npt + 1): # DO 15
106 if hru[k] >= er_h[1]:
107 iu = k
108 break
109 fx = (er_h[1] - hru[iu - 1]) / (hru[iu] - hru[iu - 1])
110
111 def lin(f):
112 return f[iu - 1] + fx * (f[iu] - f[iu - 1])
113
114 em_h[1] = lin(hs1)
115 eden_h[1] = lin(oden)
116 etem_h[1] = lin(otem)
117 ehqpr_h[1] = lin(hqpr)
118 edelr_h[1] = sdel[2, iu - 1] + fx * (sdel[2, iu] - sdel[2, iu - 1])
119 ex_h[1] = hcomp[1, iu - 1] + fx * (hcomp[1, iu] - hcomp[1, iu - 1])
120 ey_h[1] = hcomp[2, iu - 1] + fx * (hcomp[2, iu] - hcomp[2, iu - 1])
121 ez_h[1] = hcomp[3, iu - 1] + fx * (hcomp[3, iu] - hcomp[3, iu - 1])
122 if ldifli:
123 for kk in range(1, nlight + 1):
124 ii = cslight[kk]
125 eli_h[kk, 1] = (hcomp[ii, iu - 1]
126 + fx * (hcomp[ii, iu] - hcomp[ii, iu - 1]))
127
128 # Other midpoints: 4-point Lagrange interpolation. JMIN is the uppermost
129 # model point above the previous grid point (Fortran lines 121–188).
130 # Question (see the page): the interpolated composition can overshoot.
131 jmin = ibegin + 1
132 for i in range(2, npt): # DO 50
133 k0, jmin = _find_k0(er_h[i], jmin, iend, m, hru)
134 for k in range(1, 5):
135 tabler[k] = hru[k0 + k - 1]
136 interp(tabler, facinterp, facderiv, er_h[i])
137 em_h[i] = _lagrange(hs1, k0)
138 eden_h[i] = _lagrange(oden, k0)
139 etem_h[i] = _lagrange(otem, k0)
140 ehqpr_h[i] = _lagrange(hqpr, k0)
141 edelr_h[i] = _lagrange(sdel[2, :], k0)
142 ex_h[i] = _lagrange(hcomp[1, :], k0)
143 ey_h[i] = _lagrange(hcomp[2, :], k0)
144 ez_h[i] = _lagrange(hcomp[3, :], k0)
145 if ldifli:
146 for kk in range(1, nlight + 1):
147 eli_h[kk, i] = _lagrange(hcomp[cslight[kk], :], k0)
148
149 # Equally spaced radii at the zone centers (Fortran lines 190–194).
150 er[1] = hru[ibegin]
151 for i in range(2, npt + 1):
152 er[i] = er[i - 1] + dr
153
154 # First point: by definition, at the starting point (Fortran lines
155 # 199–214).
156 em[1] = hs1[ibegin]
157 eden[1] = oden[ibegin]
158 etem[1] = otem[ibegin]
159 ehqpr[1] = hqpr[ibegin]
160 edelr[1] = sdel[2, ibegin]
161 ex[1] = hcomp[1, ibegin]
162 ey[1] = hcomp[2, ibegin]
163 ez[1] = hcomp[3, ibegin]
164 if ldifli:
165 for kk in range(1, nlight + 1):
166 eli[kk, 1] = hcomp[cslight[kk], ibegin]
167
168 # Other points: 4-point Lagrange interpolation (Fortran lines 215–277).
169 jmin = ibegin + 1
170 for i in range(2, npt): # DO 70
171 k0, jmin = _find_k0(er[i], jmin, iend, m, hru)
172 for k in range(1, 5):
173 tabler[k] = hru[k0 + k - 1]
174 interp(tabler, facinterp, facderiv, er[i])
175 em[i] = _lagrange(hs1, k0)
176 eden[i] = _lagrange(oden, k0)
177 etem[i] = _lagrange(otem, k0)
178 ehqpr[i] = _lagrange(hqpr, k0)
179 edelr[i] = _lagrange(sdel[2, :], k0)
180 ex[i] = _lagrange(hcomp[1, :], k0)
181 ey[i] = _lagrange(hcomp[2, :], k0)
182 ez[i] = _lagrange(hcomp[3, :], k0)
183 if ldifli:
184 for kk in range(1, nlight + 1):
185 eli[kk, i] = _lagrange(hcomp[cslight[kk], :], k0)
186
187 # Last point: by definition, at the ending point (Fortran lines
188 # 278–292).
189 em[npt] = hs1[iend]
190 eden[npt] = oden[iend]
191 etem[npt] = otem[iend]
192 ehqpr[npt] = hqpr[iend]
193 edelr[npt] = sdel[2, iend]
194 ex[npt] = hcomp[1, iend]
195 ey[npt] = hcomp[2, iend]
196 ez[npt] = hcomp[3, iend]
197 if ldifli:
198 for kk in range(1, nlight + 1):
199 eli[kk, npt] = hcomp[cslight[kk], iend]
200
201 return dr, npt