1C
2C
3C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
4C HPOINT
5C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
6 SUBROUTINE HPOINT(M,HSTOT,HS,HS1,HS2,HT,HP,HR,LC,
7 * *HL,HD,HCOMP,PS,RS,ESTORE,ISTORE,LRESET,JXBEG,MODEL,
8 * *LSHELL,JCORE,JENV,OMEGA,ETA2,R0,HI,HJM,HKEROT,SJTOT,SKEROT,
9C * BL,DELTS,FP,FT,HG,QIW,SMASS,TEFFL) ! KC 2025-05-31
10 * * FP,FT,HG,QIW,TEFFL,CMIXL)
11C 10/15/26 MHP via Claude
12C code changed to take JSON from DIMENSIONS_MOD instead of declaring
13C PARAMETER(JSON=5000) here.
14 USE DIMENSIONS_MOD
15C 10/14/26 MHP via Claude
16C code changed to convert COMMON/TEMP/ into TEMP_MOD.
17 USE TEMP_MOD
18C 10/14/26 MHP via Claude
19C code changed to convert COMMON/SCRTCH/ into SCRTCH_MOD.
20 USE SCRTCH_MOD
21C 10/14/26 MHP via Claude
22C code changed to convert COMMON/OLDROT2/ into OLDROT2_MOD.
23 USE OLDROT2_MOD
24C 10/14/26 MHP via Claude
25C code changed to convert COMMON/OLDROT/ into OLDROT_MOD.
26 USE OLDROT_MOD
27C 10/14/26 MHP via Claude
28C code changed to convert COMMON/OLDPHY/ into OLDPHY_MOD.
29 USE OLDPHY_MOD
30C 10/14/26 MHP via Claude
31C code changed to convert COMMON/OLDMOD/ into OLDMOD_MOD.
32 USE OLDMOD_MOD
33C 10/14/26 MHP via Claude
34C code changed to convert COMMON/ENTROP/ into ENTROP_MOD.
35 USE ENTROP_MOD
36C 10/14/26 MHP via Claude
37C code changed to convert COMMON/DWMAX/ into DWMAX_MOD.
38 USE DWMAX_MOD
39C 10/14/26 MHP via Claude
40C code changed to convert COMMON/DEUTER/ into DEUTER_MOD.
41 USE DEUTER_MOD
42C 10/14/26 MHP via Claude
43C code changed to convert COMMON/COMP/ into COMP_MOD.
44 USE COMP_MOD
45C 10/14/26 MHP via Claude
46C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
47 USE NMLPAR_MOD
48C 10/14/26 MHP via Claude
49C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
50 USE CONSTANTS_MOD
51C 10/14/26 MHP via Claude
52C code changed to convert COMMON/IOUNITS/ into IOUNITS_MOD.
53 USE IOUNITS_MOD
54C 10/20/26 MHP via Claude
55C code changed to replace implicit typing with IMPLICIT NONE and
56C explicit declarations.
57 IMPLICIT NONE
58 REAL*8 CHI,CHIPREV,CMIXL,DCHI,DELCHI,DELP,DL,DM,DP,DR,DS1,DS2,DS3,
59 * * DSS,DW,DX,DZ,ESTORE,ETA2,FAC,FP,FPX,FT,FTX,HCOMP,HD,HFO,HG,
60 * * HI,HJ,HJM,HKEROT,HKO,HL,HLMAX,HP,HPMAX,HR,HS,HS1,HS2,HSTOT,
61 * * HT,OMEGA,OMEGAL,PMAX1,PMAX2,PMAX3,PMAX4,PMAX5,PS,QIW,R0,RS,
62 * * SJTOT,SKEROT,SUMJ,SUMKE,TEFFL,TESTP,WLBOT,WLTOP,WMID,X,
63 * * XTAB,Y,Y2,YTAB
64 INTEGER I,I0,ID,IEND,IFLAG,IIFLG,IM,ISTORE,IXFLAG,IXX,J,JBEG,
65 * * JCORE,JEND,JENV,JFINE,JJ,JOS,JPREV,JXBEG,K,KHI,KLO,M,
66 * * MINMIN,MM,MNEW,MODEL,MRZONE,MXZONE,NFLAG,NN,NP,NPT,NRZONE,
67 * * NTAB,NTEMP,NTOT,NZONE
68 LOGICAL*4 LC,LCZ,LDONE,LRESET,LSHELL
69
70
71C MHP 10/02 ADDED MRZONE,MXZONE TO DIMENSION STATEMENTS
72 DIMENSION HS(JSON),HS1(JSON),HS2(JSON),HT(JSON),
73 * * OMEGAL(JSON),HPMAX(4),NFLAG(100),HP(JSON),
74 * * HR(JSON),HL(JSON),HD(JSON),HCOMP(15,JSON),LCZ(JSON),FTX(JSON),
75 * * OMEGA(JSON),ETA2(JSON),R0(JSON),HI(JSON),HJM(JSON),
76 * * HKEROT(JSON),FP(JSON),FT(JSON),HG(JSON),LC(JSON),QIW(JSON),
77 * * FPX(JSON),
78 * * MRZONE(13,2),MXZONE(12,2)
79 DIMENSION PS(3),RS(3),ESTORE(4)
80C 9/25/26 MHP via Claude
81C code changed to consolidate all I/O logical unit numbers, previously
82C scattered across COMMON/LUOUT/, COMMON/LUNUM/, COMMON/ALEX06/,
83C COMMON/ACDPTH/, COMMON/NEWOPAC/, COMMON/LOPAL95/, COMMON/ATMOS2/,
84C COMMON/ALATM03/, COMMON/OPALEOS/, and COMMON/SCV2/, into a single
85C COMMON/IOUNITS/
86C 10/11/26 MHP via Claude
87C code changed to remove LSCRIB from COMMON/CCOUT/: it was declared
88C positionally in all 17 files sharing this block but never read or
89C written in executable code anywhere, and no namelist file sets it.
90C 10/12/26 MHP via Claude
91C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
92C namelist variables that the physics routines read from 27 COMMON
93C blocks which also held derived or working members. Those blocks keep
94C only their non-namelist members; five of them -- NEWMX, VMULT,
95C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
96C Derivation-only namelist variables from the same blocks went to
97C COMMON/NMLBYPASS/ instead, not here.
98C
99C Declared identically in all 121 files that hold any of these members.
100C Generated from one member list, so every copy is byte-identical; the
101C linker's 'size of symbol changed' warning is the check that they are.
102C 10/13/26 MHP via Claude: removed the unused COMMON/CCOUT/ declaration
103C (no member referenced here; residue of the obsolete-option removals).
104C 9/25/26 MHP via Claude
105C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
106C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
107C 9/24/26 MHP via Claude
108C code changed to pass CMIXL as an explicit argument instead of via
109C common block, to reduce implicit global state ahead of the F90
110C module conversion
111C 10/13/26 MHP via Claude
112C code changed to drop COMMON/CTLIM/, declared here but never used.
113C 10/13/26 MHP via Claude: removed the unused COMMON/CTOL/ declaration
114C (no member referenced here; residue of the obsolete-option removals).
115C 10/13/26 MHP via Claude: removed the unused COMMON/DPMIX/ declaration
116C (no member referenced here; residue of the obsolete-option removals).
117C MHP 06/02
118C Time change of theta
119C 10/12/26 MHP via Claude
120C code changed to remove COMMON/OPTAB/ entirely. Once OPTOL moved to the
121C consolidated namelist block, every remaining member was write-only:
122C ZSI appeared only in a DATA statement in parmin.f, and IDT and IDD were
123C assigned the constants 15 and 5 in coefft.f, envint.f, physic.f and
124C starin.f and read nowhere in the code. They are leftovers from the
125C removed opacity-table interpolation schemes.
126C 7/91 ENTROPY TERM COMMON BLOCK ADDED.
127C MHP 05/02 DEUTERIUM BURNING RATE ADDED
128 DIMENSION ID(7)
129 DIMENSION HFO(JSON),HKO(JSON)
130C MHP 6/00 ADDED DUMMY VECTOR
131C MHP 7/02 ADDED CHI VECTOR - A RUNNING TOTAL OF THE NORMALIZED
132C DIFFERENCES IN M, L, P BETWEEN SHELLS THAT IS USED TO SET THE
133C POINT SPACING.
134 DIMENSION XTAB(JSON),YTAB(JSON),CHI(JSON),Y2(JSON)
135 DIMENSION IXFLAG(JSON)
136C DATA IDMAX/JSON/
137 DATA ID/1,2,4,5,6,7,9/
138 SAVE
139
140C THIS SUBROUTINE REZONES THE MODEL, SPACING THE SHELLS SUCH THAT
141C THE MAXIMUM DISTANCE BETWEEN 2 SUCCESSIVE POINTS IN P,L,X, AND Z
142C SPECIFIED BY THE USER IS NOT EXCEEDED. IT ALSO FLAGS REAL
143C DISCONTINUITIES TO PREVENT ARTIFICIAL SMOOTHING.
144 LRESET = .FALSE.
145C IEND IS THE NUMBER OF SPECIES THE PROGRAM IS KEEPING TRACK OF
146 IEND = 11
147 IF(LEXCOM) IEND = 15
148C CHECK IF TEMPERATURE OF OUTERMOST HENYEY POINT > MIMIMUM ENVELOPE T
149 IF(HT(M).LT.TENV0) THEN
150 DO 20 I = M-1,1,-1
151 IF(HT(I).GT.TENV0) THEN
152 WRITE(ISHORT,10) M,I
153 10 10 FORMAT(' OUTER POINTS DELETED OLD M =',I5,' NEW M =',I5)
154 M = I
155 SENV = HS(M) - HSTOT
156 LRESET = .TRUE.
157 GOTO 40
158 ENDIF
159 20 20 CONTINUE
160C ENTIRE MODEL HAS T<TENV0 - UNLIKELY - BUT STOP IF TRUE
161 WRITE(ISHORT,30)
162 WRITE(IOWR,30)
163 30 30 FORMAT(1X,39('>'),40('<')/1X,'ERROR IN HPOINT'/
164 * * 1X,'MAX. STAR T LESS THAN MINIMUM ENVELOPE T.RUN STOPPED')
165C 10/30/26 MHP via Claude: bare STOP -> STOP 1, the run-time error code (issue 38).
166 STOP 1
167 40 40 CONTINUE
168C CHECK IF OUTER POINT T < MAXIMUM ENVELOPE T
169 ELSE IF(HT(M).GT.TENV1.AND.ISTORE.NE.0) THEN
170 M = M + 1
171 SENV = ESTORE(4)
172 HS(M) = HSTOT + SENV
173 HP(M) = HP(M-1) + (ESTORE(1) - PS(ISTORE))
174 HT(M) = HT(M-1) + (ESTORE(1) - PS(ISTORE))*0.250D0
175 HR(M) = HR(M-1) + (ESTORE(3) - RS(ISTORE))
176 HL(M) = HL(M-1)
177 DO 50 I = 1,IEND
178 HCOMP(I,M) = HCOMP(I,M-1)
179 50 50 CONTINUE
180 HD(M) = HP(M) - HT(M) - 8.0D0
181 J = M - 1
182 WRITE(ISHORT,60) J,HS(J),HP(J),HT(J),HR(J),M,HS(M),HP(M),
183 * * HT(M),HR(M)
184 60 60 FORMAT(' OUTER POINT ADDED',I5,F15.10,' PTR',3F10.6)
185 LRESET = .TRUE.
186 ENDIF
187
188
189C SET UP FLAGGED POINTS - PROGRAM WILL NOT REZONE ACROSS FLAGGED POINTS
190 IFLAG = 1
191C FLAG EDGES OF CENTRAL AND SURFACE CONVECTION ZONES
192 IF(JCORE.GT.1) THEN
193 NFLAG(IFLAG) = JCORE
194 IFLAG = IFLAG + 1
195 ENDIF
196 IF(JENV.LT.M .AND.JENV.GT.1) THEN
197 NFLAG(IFLAG) = JENV
198 IFLAG = IFLAG + 1
199 ENDIF
200C FLAG EDGE OF H SHELL
201 IF(LSHELL.AND.JXBEG.GT.1) THEN
202 NFLAG(IFLAG) = JXBEG - 1
203 IFLAG = IFLAG + 1
204 ENDIF
205 DO 120 I = 2,M
206C TEST FOR FLAGGING DUE TO X GRADIENT
207 IF(DABS(HCOMP(1,I)-HCOMP(1,I-1)).GT.HPTTOL(3)) THEN
208 NFLAG(IFLAG) = I
209 IFLAG = IFLAG + 1
210C TEST FOR FLAGGING DUE TO Z GRADIENT
211 ELSE IF(DABS(HCOMP(3,I)-HCOMP(3,I-1)).GT.HPTTOL(4)) THEN
212 NFLAG(IFLAG) = I
213 IFLAG = IFLAG + 1
214C TEST FOR FLAGGING DUE TO GRADIENT IN LOG OMEGA.
215 ELSE IF(LROT) THEN
216 WLTOP = DLOG10(OMEGA(I))
217 WLBOT = DLOG10(OMEGA(I-1))
218 IF(DABS(WLTOP-WLBOT).GT.HPTTOL(12)) THEN
219 NFLAG(IFLAG) = I
220 IFLAG = IFLAG + 1
221 ENDIF
222 ENDIF
223 IF(IFLAG.GE.100) THEN
224 WRITE(ISHORT,110)
225 110 110 FORMAT(1X,'MORE THAN 100 FLAG POINTS-FIRST 100 RETAINED')
226 GOTO 130
227 ENDIF
228 120 120 CONTINUE
229C PMAX1 = MAX DEL LOG P BELOW SURFACE C.Z. AND BELOW FINELY ZONED
230C REGION AROUND IT.
231C PMAX2 = MAX DEL LOG P BETWEEN LOWER EDGE OF FINELY ZONED REGION
232C AROUND SURFACE C.Z. AND BASE OF OVERSHOOT REGION.
233C PMAX3 = SAME FOR OVERSHOOT REGION.
234C PMAX4 = MAX DEL LOG P ABOVE BASE OF SURFACE C.Z. IN FINELY ZONED
235C REGION AROUND IT.
236C PMAX5 = SAME FOR THE OUTER POINTS IN THE STAR.
237 PMAX1 = HPTTOL(11)
238 PMAX4 = HPTTOL(10)
239 PMAX5 = HPTTOL(8)
240 IF(.NOT.LC(M))THEN
241 JOS = M
242 JFINE = M
243 ELSE IF (JENV.EQ.1)THEN
244 JOS = 1
245 JFINE = 1
246 ELSE
247C LOCATE BASE OF OVERSHOOT REGION IF APPLICABLE.
248 IF(.NOT.LOVSTE)THEN
249 I = JENV
250 JOS = JENV
251 ELSE
252 DO 191 JOS = JENV-1,1,-1
253 IF(HP(JOS)-HP(JENV).GT.ALPHAE)GOTO 193
254 191 191 CONTINUE
255 193 193 JOS = JOS + 1
256 DELP = HP(JOS)-HP(JENV)
257 IF(DELP.GT.0.0D0) THEN
258 NP = INT(DELP/HPTTOL(10))
259 IF(MOD(DELP,HPTTOL(10)).NE.0D0)NP=NP+1
260 PMAX3 = DELP/DFLOAT(NP)
261 ELSE
262 PMAX3 = HPTTOL(10)
263 ENDIF
264 IF(JOS.GT.1)THEN
265 NFLAG(IFLAG) = JOS
266 IFLAG = IFLAG + 1
267 ENDIF
268 ENDIF
269 IF(HPTTOL(7).EQ.0.0D0) THEN
270 JFINE = JOS
271 ELSE
272C NOW LOCATE BASE OF FINELY ZONED REGION.
273 IF(JOS.EQ.1)THEN
274 JFINE = 1
275 GOTO 198
276 ENDIF
277 DO 195 JFINE = JOS-1,1,-1
278 IF(HP(JFINE) - HP(JENV).GT.HPTTOL(7))GOTO 197
279 195 195 CONTINUE
280 197 197 JFINE = JFINE + 1
281 IF(JFINE.EQ.JOS)GOTO 198
282 DELP = HP(JFINE) - HP(JOS)
283 NP = INT(DELP/HPTTOL(10))
284 IF(MOD(DELP,HPTTOL(10)).NE.0D0)NP=NP+1
285 PMAX2 = DELP/DFLOAT(NP)
286 IF(PMAX2.EQ.0.0D0)PMAX2 = HPTTOL(10)
287 IF(JFINE.GT.1)THEN
288 NFLAG(IFLAG) = JFINE
289 IFLAG = IFLAG + 1
290 ENDIF
291 198 198 CONTINUE
292 ENDIF
293 ENDIF
294 130 130 NFLAG(IFLAG) = M
295C ARRANGE THE FLAG POINTS IN ASCENDING ORDER
296 IF(IFLAG.EQ.1) GOTO 180
297 140 140 CONTINUE
298 LDONE = .TRUE.
299 DO 150 I = 1,IFLAG-1
300 IF (NFLAG(I+1).LT.NFLAG(I)) THEN
301 NTEMP = NFLAG(I)
302 NFLAG(I) = NFLAG(I+1)
303 NFLAG(I+1) = NTEMP
304 LDONE = .FALSE.
305 ENDIF
306 150 150 CONTINUE
307 IF(.NOT.LDONE) GOTO 140
308C ENSURE THAT POINTS ARENT FLAGGED MORE THAN ONCE.
309 I = 2
310 160 160 CONTINUE
311 IF(NFLAG(I).EQ.NFLAG(I-1))THEN
312 IF(I.LT.IFLAG) THEN
313 DO 170 J = I,IFLAG-1
314 NFLAG(J) = NFLAG(J+1)
315 170 170 CONTINUE
316 ENDIF
317 IFLAG = IFLAG - 1
318 ENDIF
319 I = I + 1
320 IF(I.LE.IFLAG) GOTO 160
321 180 180 CONTINUE
322 WRITE(ISHORT,185) (NFLAG(J),J=1,IFLAG)
323 185 185 FORMAT(1X,'FLAG-POINTS',20I4)
324C BEGIN REFLOATING OF POINTS
325 IF(LROT) THEN
326 DO 190 I = 1,M
327 IF(OMEGA(I).GT.0.0D0) THEN
328 OMEGAL(I) = DLOG10(OMEGA(I))
329 ELSE
330 OMEGAL(I) = 0.0D0
331 ENDIF
332 190 190 CONTINUE
333 ENDIF
334 HSS(1) = HS(1)
335 HPO(1) = HP(1)
336 HLO(1) = HL(1)
337 HKO(1) = HCOMP(1,1)
338 HFO(1) = HCOMP(3,1)
339 HLMAX = HL(M)
340C JVS 04/14 added Teff to saved variables
341 TEFFLO = TEFFL
342C 10/29/26 MHP via Claude
343C code changed to save the surface luminosity, HLSURO, in place of the
344C point count MO. HPOINT re-splines HLO onto the new mesh, so ENTIME's
345C HLO(MO) read an interior point or a stale entry whenever the count
346C changed.
347 HLSURO = HL(M)
348 DO I = M-1,1,-1
349 IF(HL(I).GT.HLMAX)THEN
350 HLMAX = HL(I)
351 ENDIF
352 END DO
353 HPMAX(1) = HPTTOL(8)
354 HPMAX(2) = HPTTOL(9)*HLMAX
355 HPMAX(3) = HPTTOL(5)
356 HPMAX(4) = HPTTOL(6)
357C KFACT = 0
358C 200 CONTINUE
359 IIFLG = 1
360 J = 2
361 I0 = 2
362C CHI IS THE NORMALIZED VECTOR OF DIFFERENCES IN M,L,P:
363C CHI = HS/DELTA M + HL/DELTA L - HP/DELTA P
364 DM = HPTTOL(2)
365 DL = HPMAX(2)
366 CHI(1) = 1.0D0
367 DO J = 2, M
368 TESTP = HP(J) - HP(JENV)
369 IF(ABS(TESTP).LT.HPTTOL(7))THEN
370C FINELY ZONED REGION
371 DP = HPTTOL(10)
372 ELSE IF(TESTP.GT.HPTTOL(7))THEN
373C BELOW SURFACE CZ
374 DP = HPTTOL(11)
375 ELSE
376C IN SURFACE CZ
377 DP = HPTTOL(8)
378 ENDIF
379 IF(HL(J).GT.HL(J-1))THEN
380 DCHI = (HS(J)-HS(J-1))/DM +
381 * * (HL(J)-HL(J-1))/DL -
382 * * (HP(J)-HP(J-1))/DP
383 ELSE
384 DCHI = (HS(J)-HS(J-1))/DM -
385 * * (HP(J)-HP(J-1))/DP
386 ENDIF
387 CHI(J) = CHI(J-1)+DCHI
388 END DO
389 DO J = 1,M
390 XTAB(J) = CHI(J)
391 YTAB(J) = HS(J)
392 END DO
393C GET SPLINE COEFFICIENTS
394 CALL SPLINC(XTAB,YTAB,Y2,M)
395 CHIPREV = CHI(1)
396 JPREV = 1
397 MNEW = 1
398 DO I = 1,IFLAG
399 DELCHI = CHI(NFLAG(I))-CHIPREV
400 NPT = INT(DELCHI)+1
401 IF(MNEW+NPT.GT.JSON)THEN
402C EXCEEDED ARRAY DIMENSIONS; COMPLAIN AND STOP
403 WRITE(*,101)MNEW+NPT,JSON
404 101 101 FORMAT(' DESIRED NUMBER OF POINTS ',I6,'EXCEEEDS JSON ',
405 * * I6/' RUN STOPPED')
406 STOP 9999
407 ENDIF
408 DCHI = DELCHI/DFLOAT(NPT)
409C ASSIGN NEW POINTS
410 DO J = JPREV+1,JPREV+NPT
411 X = CHIPREV + DCHI
412 CALL SPLINTD2(XTAB, YTAB, M, Y2, X, Y, KLO, KHI)
413 HSS(J) = Y
414 CHIPREV = X
415C
416
417 END DO
418 MNEW = MNEW + NPT
419 JPREV = MNEW
420C
421 END DO
422
423
424
425
426
427
428
429C TEST FOR ASSIGNING POINTS BASED ON THE GRADIENT IN X.
430 DO J = 1,M
431 XTAB(J) = HS(J)
432 YTAB(J) = HCOMP(1,J)
433 END DO
434C GET SPLINE COEFFICIENTS
435 CALL SPLINC(XTAB,YTAB,Y2,M)
436C ASSIGN INTERPOLATED VECTOR OF X VALUES TO HIO
437 DO I = 2,MNEW
438 X = HSS(I)
439 CALL SPLINTD2(XTAB, YTAB, M, Y2, X, Y, KLO, KHI)
440 HKO(I) = Y
441 END DO
442
443
444
445
446C SKIP IF HPMAX(3) IS ZEROED OUT
447 IF(HPMAX(3).LE.1.0D-15)GOTO 102
448C TEST ON X-CHANGE (ONLY FOR INCREASING X) USING HIO AS DUMMY ARRAY
449 IXX = 0
450 DO J = MNEW,2,-1
451 IF(HKO(J)-HKO(J-1).GT.HPMAX(3)) THEN
452 IXX = IXX + 1
453 IXFLAG(IXX) = J
454 ENDIF
455 END DO
456 IF(IXX.EQ.0)GOTO 102
457 MM = MNEW
458 DO I = 1,IXX
459 J = IXFLAG(I)
460 DX = (HKO(J) - HKO(J-1))/HPMAX(3)
461C NUMBER OF NEW POINTS NEEDED
462 NN = INT(DX)
463C 10/30/26 MHP via Claude: stop before the insertion runs past JSON, as
464C the chi placement above already does.
465 IF(MM+NN.GT.JSON)THEN
466 WRITE(*,104)'X',MM+NN,JSON
467 WRITE(ISHORT,104)'X',MM+NN,JSON
468 STOP 1
469 ENDIF
470C
471 DSS = (HSS(J)-HSS(J-1))/DFLOAT(NN+1)
472 DO K = MM+NN,J+NN,-1
473 HSS(K) = HSS(K-NN)
474C
475 END DO
476 DO K = J + NN -1, J -1, -1
477 HSS(K) = HSS(K+1) - DSS
478 END DO
479 MM = MM + NN
480 END DO
481 MNEW = MM
482C
483 102 102 CONTINUE
484 104 104 FORMAT(' HPOINT: ',A,' POINT INSERTION NEEDS',I7,' POINTS; JSON IS',
485 * * I7/' RUN STOPPED')
486C TEST FOR ASSIGNING POINTS BASED ON THE GRADIENT IN Z.
487 DO J = 1,M
488 XTAB(J) = HS(J)
489 YTAB(J) = HCOMP(3,J)
490 END DO
491C GET SPLINE COEFFICIENTS
492 CALL SPLINC(XTAB,YTAB,Y2,M)
493C ASSIGN INTERPOLATED VECTOR OF Z VALUES TO HGO
494 DO I = 2,MNEW
495 X = HSS(I)
496 CALL SPLINTD2(XTAB, YTAB, M, Y2, X, Y, KLO, KHI)
497 HFO(I) = Y
498C
499 END DO
500C TEST ON Z-CHANGE (ONLY FOR DECREASING Z) USING HIO AS DUMMY ARRAY
501C SKIP IF HPMAX(4) IS ZEROED OUT
502C
503
504 IF(HPMAX(4).LE.1.0D-15)GOTO 103
505 IXX = 0
506 DO J = MNEW,2,-1
507 IF(HFO(J-1)-HFO(J).GT.HPMAX(4)) THEN
508 IXX = IXX + 1
509 IXFLAG(IXX) = J
510 ENDIF
511 END DO
512C
513 IF(IXX.EQ.0)GOTO 103
514 MM = MNEW
515C
516 DO I = 1,IXX
517 J = IXFLAG(I)
518 DZ = (HFO(J-1) - HFO(J))/HPMAX(4)
519C NUMBER OF NEW POINTS NEEDED
520 NN = INT(DZ)
521C 10/30/26 MHP via Claude: stop before the insertion runs past JSON, as
522C the chi placement above already does.
523 IF(MM+NN.GT.JSON)THEN
524 WRITE(*,104)'Z',MM+NN,JSON
525 WRITE(ISHORT,104)'Z',MM+NN,JSON
526 STOP 1
527 ENDIF
528 DSS = (HSS(J)-HSS(J-1))/DFLOAT(NN+1)
529 DO K = MM+NN,J+NN,-1
530 HSS(K) = HSS(K-NN)
531 END DO
532 DO K = J + NN -1, J -1, -1
533 HSS(K) = HSS(K+1) - DSS
534 END DO
535 MM = MM + NN
536 END DO
537 MNEW = MM
538C
539 103 103 CONTINUE
540C DELETE NEW POINTS THAT ARE TOO CLOSE TOGETHER.
541C (NOTE HDO IS BEING USED AS A DUMMY ARRAY HERE).
542 J = 1
543 HDO(J) = HSS(J)
544 DO 810 JJ = 2,MNEW-1
545C
546 IF(HSS(JJ) - HDO(J).GT.HPTTOL(1))THEN
547 J = J + 1
548 HDO(J) = HSS(JJ)
549 ENDIF
550 810 810 CONTINUE
551 J = J + 1
552 HDO(J) = HSS(MNEW)
553 MNEW = J
554 DO 820 J = 2,MNEW
555 HSS(J) = HDO(J)
556 820 820 CONTINUE
557C
558
559C NOW LOCATE OUTER EDGE OF CONVECTIVE CORE AND INNER EDGE OF CONVECTIVE
560C ENVELOPE IN THE NEW POINT DISTRIBUTION.
561 IF(JCORE.GT.1)THEN
562 DO 823 J = 2,MNEW
563 IF(HSS(J).GT.HS(JCORE))GOTO 824
564 823 823 CONTINUE
565 824 824 JCORE = J - 1
566 ELSE
567 JCORE = 1
568 ENDIF
569 IF(JENV.LT.M)THEN
570 DO 825 J = MNEW-1,1,-1
571 IF(HSS(J).LT.HS(JENV))GOTO 826
572 825 825 CONTINUE
573 826 826 JENV = J + 1
574 ELSE
575 JENV = MNEW
576 ENDIF
577 IF(JCORE.GT.1)THEN
578 DO 827 I = 1,JCORE
579 LC(I) = .TRUE.
580 827 827 CONTINUE
581 JBEG = JCORE + 1
582 ELSE
583 JBEG = 1
584 ENDIF
585 IF(JENV.LT.MNEW)THEN
586 DO 828 I = JENV,MNEW
587 LC(I) = .TRUE.
588 828 828 CONTINUE
589 JEND = JENV - 1
590 ELSE
591 JEND = MNEW
592 ENDIF
593 IF(JEND.LT.1.OR.JBEG.GT.MNEW) GOTO 830
594 DO 829 J = JBEG,JEND
595 LC(J) = .FALSE.
596 829 829 CONTINUE
597 830 830 CONTINUE
598
599
600C NOW USE AN OSCILLATORY SPLINE TO FIT THE OLD RUN OF PHYSICAL VARIABLES
601C AT THE NEW RUN OF MASS POINTS.
602 NTAB = M
603 NTOT = MNEW
604C XVAL=RUN OF NEW MODEL MASS COORDINATES(HSS)
605C XTAB = RUN OF OLD MODEL MASS CO-ORDINATES(HS)
606C YTAB = RUN OF VARIABLE WHOSE VALUE AT THE NEW MASS POINTS
607C IS DESIRED(HP,HT,HL,HR,HD,ETC.)
608C NTAB = NUMBER OF DATA POINTS(M)
609C NTOT=NUMBER OF POINTS AT WHICH SPLINE IS TO BE EVALUTED(MNEW)
610C YVAL = OUTPUT RUN OF VARIABLE VALUES AT THE NEW RUN OF MASS POINTS.
611C FORM OF CALL IS CALL OSPLIN(XVAL,YVAL,XTAB,YTAB,NTAB,NTOT)
612C DO EACH COMPOSITION IN ORDER USING HPO AND HTO AS DUMMY ARRAYS.
613C 7/91 ADD ENTROPY TERM INTERPOLATION.
614 DO 904 J = 1,M
615 HPO(J) = HTT0(J)
616 904 904 CONTINUE
617 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
618 DO 905 J = 1,MNEW
619 HTT0(J) = HTO(J)
620 905 905 CONTINUE
621
622C
623
624
625 DO 906 J = 1,M
626 HPO(J) = HPP0(J)
627 906 906 CONTINUE
628 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
629 DO 907 J = 1,MNEW
630 HPP0(J) = HTO(J)
631 907 907 CONTINUE
632 DO 911 J = 1,M
633 HPO(J) = HLL0(J)
634 911 911 CONTINUE
635 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
636 DO 912 J = 1,MNEW
637 HLL0(J) = HTO(J)
638 912 912 CONTINUE
639 DO 913 J = 1,M
640 HPO(J) = HRR0(J)
641 913 913 CONTINUE
642 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
643 DO 914 J = 1,MNEW
644 HRR0(J) = HTO(J)
645 914 914 CONTINUE
646
647
648 DO 850 I = 1,IEND
649 DO 833 J = 1,M
650 HPO(J) = HCOMP(I,J)
651 833 833 CONTINUE
652 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
653 DO 835 J = 1,MNEW
654 HCOMP(I,J) = HTO(J)
655 835 835 CONTINUE
656C HCOMPP IS THE ARRAY OF COMPOSITION AT THE BEGINNING OF THE TIMESTEP.
657C THIS IS NEEDED FOR COMPOSITION DIFFUSION IN ROTATING MODELS.
658 DO 840 J = 1,M
659 HPO(J) = HCOMPP(I,J)
660 840 840 CONTINUE
661 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
662 DO 845 J = 1,MNEW
663 HCOMPP(I,J) = HTO(J)
664 845 845 CONTINUE
665 850 850 CONTINUE
666
667
668C 10/30/26 MHP via Claude
669C code changed to drop the regrid of HCOMPM, which nothing read.
670C MHP 05/02 IF THE SURFACE DEUTERIUM IS ABOVE
671C THRESHOLD (1.0D-14) FIND THE NEW RUN OF
672C DEUTERIUM BURNING RATES
673C 10/29/26 MHP via Claude
674C code changed to regrid DRATE0 unconditionally. The gate tested
675C HCOMP(12,M) after HCOMP had moved to the new mesh but while M was
676C still the old count, so it read an interior point or a stale entry;
677C when it failed, DRATE0 stayed in old-mesh order and DBURN and MIDMOD
678C read it zone by zone on the new mesh.
679 DO J = 1,M
680 HPO(J) = DRATE0(J)
681 END DO
682 CALL OSPLIN(HSS,HTO,HS,HPO,NTAB,NTOT)
683 DO J = 1,MNEW
684 DRATE0(J) = HTO(J)
685 END DO
686C NOW FIND RUN OF P,R,L,T,AND RHO IN THAT ORDER FOR THE NEW POINTS.
687
688 CALL OSPLIN(HSS,HPO,HS,HP,NTAB,NTOT)
689 CALL OSPLIN(HSS,HRO,HS,HR,NTAB,NTOT)
690 CALL OSPLIN(HSS,HLO,HS,HL,NTAB,NTOT)
691 CALL OSPLIN(HSS,HTO,HS,HT,NTAB,NTOT)
692 CALL OSPLIN(HSS,HDO,HS,HD,NTAB,NTOT)
693
694C FOR ROTATING MODELS FIND THE NEW RUN OF OMEGA,J/M,FP,FT,R0,AND ETA2.
695 IF(LROT) THEN
696 CALL OSPLIN(HSS,WOLD,HS,OMEGA,NTAB,NTOT)
697 CALL OSPLIN(HSS,HJX,HS,HJM,NTAB,NTOT)
698 CALL OSPLIN(HSS,FPX,HS,FP,NTAB,NTOT)
699 CALL OSPLIN(HSS,FTX,HS,FT,NTAB,NTOT)
700 CALL OSPLIN(HSS,R0X,HS,R0,NTAB,NTOT)
701 CALL OSPLIN(HSS,ETA2X,HS,ETA2,NTAB,NTOT)
702 ENDIF
703C
704
705C SPIT OUT POINT DISTRIBUTION DETAILS IF REQUESTED
706 IF(LDEBUG .AND. NPOINT.LT.9999) THEN
707 IF(MOD(MODEL,NPOINT).EQ.0) THEN
708 MINMIN = MIN0(M,MNEW)
709C
710 WRITE(IDEBUG,910)
711 910 910 FORMAT('1',20X,'OLD POINTS',54X,'NEW POINTS'/2(3X,'N',5X,'S',
712 * * 8X,'P',7X,'T',7X,'R',8X,'L',7X,'X',4X,'Z',3X,'O16',1X) )
713 WRITE(IDEBUG,920) (I,HS(I),HP(I),HT(I),HR(I),HL(I),
714 * * HKO(I),HFO(I),HCOMP(9,I),I,HSS(I),HPO(I),HTO(I),
715 * * HRO(I),HLO(I),HCOMP(1,I),HCOMP(3,I),HCOMP(9,I), I = 1,MINMIN)
716 920 920 FORMAT( 2(1X,I3,F11.7,F8.4,F8.5,F8.4,1PE9.2,0PF6.3,2F5.3) )
717 IF(M.GT.MINMIN) THEN
718 MINMIN = MINMIN + 1
719 WRITE(IDEBUG,930) (I,HS(I),HP(I),HT(I),HR(I),HL(I),
720 * * HKO(I),HFO(I),HCOMP(9,I),I=MINMIN,M)
721 930 930 FORMAT( 1X,I3,F11.7,F8.4,F8.5,F8.4,1PE9.2,0PF6.3,2F5.3)
722 ELSE IF(MNEW.GT.MINMIN) THEN
723 MINMIN = MINMIN + 1
724 WRITE(IDEBUG,940)(I,HSS(I),HPO(I),HTO(I),HRO(I),HLO(I),
725 * * HCOMP(1,I),HCOMP(3,I),HCOMP(9,I),I=MINMIN,MNEW)
726 940 940 FORMAT(65X,I3,F11.7,F8.4,F8.5,F8.4,1PE9.2,0PF6.3,2F5.3)
727 ENDIF
728 ENDIF
729 ENDIF
730
731
732C TRANSFER NEW POINTS.
733 DO 1000 J = 1,MNEW
734 HS(J) = HSS(J)
735 HP(J) = HPO(J)
736 HT(J) = HTO(J)
737 HR(J) = HRO(J)
738 HL(J) = HLO(J)
739 HD(J) = HDO(J)
740 1000 1000 CONTINUE
741 IF (LROT) THEN
742 DO 1005 J = 1, MNEW
743 HJM(J) = HJX(J)
744 OMEGA(J) = WOLD(J)
745 FP(J) = FPX(J)
746 FT(J) = FTX(J)
747 ETA2(J) = ETA2X(J)
748 R0(J) = R0X(J)
749 1005 1005 CONTINUE
750 ENDIF
751C MHP 6/00 INTERPOLATED IN ENERGY GENERATION AT START OF TIMESTEP
752 IF(LROT .OR. (LEXCOM .AND. LOVSTE))THEN
753 CALL OSPLIN(HSS,ESUMO,HS,SESUM,NTAB,NTOT)
754 DO IM = 1,M
755 YTAB(IM) = SESUM(IM)+SEG(6,IM)+SEG(7,IM)
756 END DO
757 CALL OSPLIN(HSS,EPSO,HS,YTAB,NTAB,NTOT)
758 ENDIF
759 WRITE(ISHORT,1020) M,MNEW
760 1020 1020 FORMAT(' POINTS OLD',I5,' NEW',I5)
761 M = MNEW
762C SET UP WEIGHTS AND MASSES
763 DS3 = DEXP(CLNDP*HS(1))
764 DS2 = - DS3
765 DO 1030 I = 2,M
766 DS1 = DS2
767 DS2 = DS3
768 DS3 = DEXP(CLNDP*HS(I))
769 HS1(I-1) = DS2
770 HS2(I-1) = 0.5D0*(DS3-DS1)
771 1030 1030 CONTINUE
772 HS1(M) = DS3
773 HS2(M) = DEXP(CLN*HSTOT) - 0.5D0*(DS2+DS3)
774 IF(LROT) THEN
775C FIRST GUESS AT MOMENT OF INERTIA(HI)
776 DO 1070 I=1,M
777 HI(I) = CC23*HS2(I)*DEXP(CLN*2.0D0*HR(I))
778 1070 1070 CONTINUE
779C CALCULATE OVERSHOOT
780 CALL OVROT(HCOMP,HD,HP,HR,HS,HT,LC,M,LCZ,MRZONE,MXZONE,
781 & & NRZONE,NZONE)
782C JNT 2025/09/03 duplicating 2015/04/06 recompute moment of interia
783C before recomputing the rotation I am less confident that this is
784C necessary since WALPCZ does run in this version but I don't think
785C it can hurt.
786 CALL MOMI(ETA2,HR,HS,HS2,1,M,OMEGA,R0,HI,QIW)
787C END JNT
788
789C FIND THE ANGULAR VELOCITY OMEGA THAT CORRESPONDS TO THE GIVEN
790C SPECIFIC ANGULAR MOMENTUM HJM.
791 CALL GETROT(HD,HJM,HR,HS,HS2,LCZ,M,ETA2,HI,OMEGA,QIW,R0)
792C CALCULATE FP,FT,R0 AND ETA2 GIVEN OMEGA
793 CALL FPFT(HD,HR,HS,M,OMEGA,ETA2,FP,FT,HG,R0)
794C FIND CORRECT MOMENT OF INERTIA(HI)
795C CALL MOMI(ETA2,HD,HR,HS,HS2,1,M,OMEGA,R0,HI,QIW,M) ! KC 2025-05-31
796 CALL MOMI(ETA2,HR,HS,HS2,1,M,OMEGA,R0,HI,QIW)
797C FIND NEW TOTAL ANGULAR MOMENTUM
798 SUMJ = 0.0D0
799 SUMKE = 0.0D0
800 DO 1110 I = 1,M
801 HJ = HJM(I)*HS2(I)
802 HKEROT(I) = 0.5D0*OMEGA(I)*HJ
803 SUMJ = SUMJ + HJ
804 SUMKE = SUMKE + HKEROT(I)
805 1110 1110 CONTINUE
806 WRITE(ISHORT,1120)SJTOT,SUMJ,SKEROT,SUMKE
807 1120 1120 FORMAT(1X,'TOTAL J OF STAR - PREVIOUS ',1PE21.13,' NEW ',
808 * * 1PE21.13/' TOTAL ROTATIONAL K.E. OF STAR-PREVIOUS ',1PE21.13,
809 * * ' NEW ',1PE21.13)
810 SJTOT = SUMJ
811 SKEROT = SUMKE
812C STORE THE OLD MODEL STRUCTURE FOR USE IN DIFFUSION.
813 DO 1130 I = 1,M
814 WOLD(I) = OMEGA(I)
815 HGO(I) = HG(I)
816 HIO(I) = HI(I)
817 ETA2X(I) = ETA2(I)
818 R0X(I) = R0(I)
819 LCO(I) = LC(I)
820 LCZO(I) = LCZ(I)
821C MHP 10/91 J/M STORED IN HJX FOR I/O USE.
822 HJX(I) = HJM(I)
823 1130 1130 CONTINUE
824C MHP 9/91 CHANGE : T GRADIENTS STORED IF LEXCOM=T AND LOVSTE=T; OR FOR
825C ROTATION; THIS IS NEEDED SO THAT THE BASE OF THE OVERSHOOT REGION FOR
826C PRE-MS MODELS CAN BE ACCURATELY LOCATED.
827 ENDIF
828 IF(LROT .OR. (LEXCOM .AND. LOVSTE))THEN
829C END OF 9/91 CHANGE
830C FIND THE NEW RUN OF PHYSICAL VARIABLES AT THE NEW SET OF POINTS;
831C THIS IS NEEDED EVEN IN THE ABSENCE OF DIFFUSION TO ACCURATELY LOCATE
832C THE EDGES OF CONVECTION ZONES.
833C CALL PHYSIC(FP,FT,HCOMP,HD,HG,HL,HP,HR,HS,HT,LC,LCZ,M,TEFFL) ! KC 2025-05-31
834 CALL PHYSIC(FP,FT,HCOMP,HD,HG,HL,HP,HR,HS,HT,LC,M,TEFFL,CMIXL)
835C FOR DIFFUSION STORE THE AUXILLARY QUANTITIES NEEDED TO CALCULATE
836C VELOCITIES AT THE START OF THE TIMESTEP WITH THE NEW POINT DISTRIBUTION
837C SO THAT A SERIES OF SMALL DIFFUSION TIMESTEPS CAN BE TAKEN WITHIN
838C ONE LARGE EVOLUTIONARY TIMESTEP.
839 DO 1040 IM = 1,M
840 DELRO(IM) = SDEL(1,IM)
841 DELO(IM) = SDEL(2,IM)
842 DELAO(IM) = SDEL(3,IM)
843 AMUO(IM) = HAMU(IM)
844 OO(IM) = SO(IM)
845 CPO(IM) = CP(IM)
846 QDTO(IM) = SQDT(IM)
847 VELO(IM) = SVEL(IM)
848 VISCO(IM) = VISC(IM)
849 THDIFO(IM) = THDIF(IM)
850C 10/30/26 MHP via Claude
851C code changed to drop the store of DDELM (MHP 06/02). SETUPV overwrites
852C it over the same zones before VCIRC reads it, in every SECULR region.
853C MHP 6/00 CALCULATED EARLIER
854C ESUMO(IM) = SESUM(IM)
855 QWRMX0(IM) = QWRMAX(IM)
856 1040 1040 CONTINUE
857C MHP 06/02 ADDED TERM FOR THE TIME EVOLUTION
858C OF THE ANGULAR VELOCITY DISTRIBUTION
859 DO I = 2,M
860 DR = EXP(CLN*HR(I))-EXP(CLN*HR(I-1))
861 DW = OMEGA(I) - OMEGA(I-1)
862 WMID = 0.5D0*(OMEGA(I)+OMEGA(I-1))
863 FAC = 2.0D0*(HR(I)+HR(I-1))-0.5D0*
864 * * (HS(I)+HS(I-1))-CGL
865 THO(I) = EXP(CLN*FAC)*WMID*DW/DR
866 QWRST(I) = DW/DR
867 END DO
868 ENDIF
869C CALCULATE NEW SURFACE OPACITY TABLE IF NEEDED.
870 IF(DABS(XNEW-HCOMP(1,M)).GT.1.0D-8) THEN
871 XNEW = HCOMP(1,M)
872 ZNEW = HCOMP(3,M)
873 CALL SURFOPAC(XNEW)
874
875 END IF
876
877 RETURN
878 END1"""Python version of hpoint.f (YREC 7be4133): rezoning the model at the
2start of each step."""
3
4import math
5import sys
6
7import numpy as np
8
9from pyrec import comp_mod
10from pyrec import constants_mod
11from pyrec import deuter_mod
12from pyrec import dimensions_mod
13from pyrec import dwmax_mod
14from pyrec import entrop_mod
15from pyrec import iounits_mod
16from pyrec import nmlpar_mod
17from pyrec import oldmod_mod
18from pyrec import oldphy_mod
19from pyrec import oldrot2_mod
20from pyrec import oldrot_mod
21from pyrec import scrtch_mod
22from pyrec import temp_mod
23from pyrec.fpft import fpft
24from pyrec.getrot import getrot
25from pyrec.momi import momi
26from pyrec.osplin import osplin
27from pyrec.ovrot import ovrot
28from pyrec.physic import physic
29from pyrec.splinc import splinc
30from pyrec.splintd2 import splintd2
31from pyrec.surfopac import surfopac
32
33JSON = dimensions_mod.json
34
35# The Fortran's local arrays (Fortran lines 72–79, 128–137). HPOINT has
36# SAVE, so they keep their values between calls; they are module-level here
37# for the same reason (the debug table can print entries of HKO and HFO left
38# from an earlier call).
39omegal = np.zeros(JSON + 1)
40hpmax = np.zeros(5)
41# Suspected bug (see the page): the Fortran can write NFLAG(101), past its
42# 100 elements; the Python's index 101 keeps it in bounds.
43nflag = np.zeros(102, dtype=int) # NFLAG(100), index 0 unused
44lcz = np.zeros(JSON + 1, dtype=bool)
45ftx = np.zeros(JSON + 1)
46fpx = np.zeros(JSON + 1)
47mrzone = np.zeros((14, 3), dtype=int)
48mxzone = np.zeros((13, 3), dtype=int)
49hfo = np.zeros(JSON + 1)
50hko = np.zeros(JSON + 1)
51xtab = np.zeros(JSON + 1)
52ytab = np.zeros(JSON + 1)
53chi = np.zeros(JSON + 1)
54y2 = np.zeros(JSON + 1)
55ixflag = np.zeros(JSON + 1, dtype=int)
56# DATA ID: the species of HCOMPM that were interpolated (index 0 unused);
57# still declared in the Fortran, unused since the regrid of HCOMPM went.
58ID = np.array([0, 1, 2, 4, 5, 6, 7, 9])
59
60
61def _stop_insertion(what, npts):
62 # FORMAT 104, written to the terminal and ISHORT, then STOP 1: the X or
63 # Z point insertion would run past JSON.
64 msg = (f" HPOINT: {what} POINT INSERTION NEEDS{npts:7d} POINTS; JSON IS"
65 f"{JSON:7d}\n RUN STOPPED")
66 print(msg)
67 iounits_mod.write(iounits_mod.ishort, msg)
68 sys.exit(1)
69
70
71def _fmt_row(i, s, p, t, r, l, x, z, o16):
72 # 1X,I3,F11.7,F8.4,F8.5,F8.4,1PE9.2,0PF6.3,2F5.3
73 return (f" {i:3d}{s:11.7f}{p:8.4f}{t:8.5f}{r:8.4f}{l:9.2E}"
74 f"{x:6.3f}{z:5.3f}{o16:5.3f}")
75
76
77def hpoint(m: int, hstot: float, hs: np.ndarray, hs1: np.ndarray, hs2: np.ndarray, ht: np.ndarray, hp: np.ndarray,
78 hr: np.ndarray, lc: np.ndarray, hl: np.ndarray, hd: np.ndarray, hcomp: np.ndarray, ps: np.ndarray,
79 rs: np.ndarray, estore: np.ndarray, istore: int, lreset: bool, jxbeg: int, model: int, lshell: bool,
80 jcore: int, jenv: int, omega: np.ndarray, eta2: np.ndarray, r0: np.ndarray, hi: np.ndarray, hjm: np.ndarray,
81 hkerot: np.ndarray, sjtot: float, skerot: float, fp: np.ndarray, ft: np.ndarray, hg: np.ndarray,
82 qiw: np.ndarray, teffl: float, cmixl: float) -> tuple[int, bool, int, int, float, float]:
83 """Rezone the model: keep the jumps between neighbouring points in
84 mass, L, P, X and Z below the user's limits (HPTTOL), keep
85 discontinuities as fixed points, add or drop outer points at the
86 envelope temperature limits, interpolate every variable to the new
87 points, recompute the shell masses and, for rotating models, the
88 rotation and the start-of-step physics.
89
90 Translates: hpoint.f#HPOINT (7be4133)
91
92 Arguments: the model (hs = log m, hp, ht, hr, hl, hd, hcomp, lc, and m
93 points), hstot (log M), the envelope fit (ps, rs, estore, istore), the
94 convection and shell indices (jcore, jenv, jxbeg, lshell), model, the
95 rotation arrays (omega, eta2, r0, hi, hjm, hkerot, fp, ft, hg, qiw), the
96 totals sjtot and skerot, teffl, and cmixl (the run's mixing length,
97 passed on to physic). Arrays are changed in place, hs1 and hs2 set.
98 lreset is output only.
99
100 Returns (m, lreset, jcore, jenv, sjtot, skerot).
101
102 """
103
104 # Outputs of SPLINTD2, set before its first call.
105 y = 0.0
106 klo = khi = 0
107
108 # Rezone so that the user's maximum jumps between successive points in
109 # P, L, X and Z are not exceeded; flag real discontinuities. IEND is the
110 # number of species followed (Fortran lines 144–147).
111 lreset = False
112 iend = 11
113 if nmlpar_mod.lexcom:
114 iend = 15
115
116 # Outermost Henyey point colder than the minimum envelope T: drop points
117 # (Fortran lines 149–167).
118 # Question (see the page): the documentation says the code stops.
119 if ht[m] < nmlpar_mod.tenv0:
120 for i in range(m - 1, 0, -1): # loop 20
121 if ht[i] > nmlpar_mod.tenv0:
122 iounits_mod.write(iounits_mod.ishort,
123 f" OUTER POINTS DELETED OLD M ={m:5d}"
124 f" NEW M ={i:5d}")
125 m = i
126 comp_mod.senv = hs[m] - hstot
127 lreset = True
128 break # to label 40
129 else:
130 # The entire model has T < TENV0: stop
131 msg = (" " + ">" * 39 + "<" * 40 + "\n ERROR IN HPOINT\n"
132 " MAX. STAR T LESS THAN MINIMUM ENVELOPE T.RUN STOPPED")
133 iounits_mod.write(iounits_mod.ishort, msg)
134 iounits_mod.write(iounits_mod.iowr, msg)
135 sys.exit(1)
136
137 # Outermost point hotter than the maximum envelope T: add one point
138 # (Fortran lines 169–186).
139 elif ht[m] > nmlpar_mod.tenv1 and istore != 0:
140 m = m + 1
141 comp_mod.senv = estore[4]
142 hs[m] = hstot + comp_mod.senv
143 hp[m] = hp[m - 1] + (estore[1] - ps[istore])
144 # Question (see the page): rough guesses for the added point's T, rho.
145 ht[m] = ht[m - 1] + (estore[1] - ps[istore]) * 0.250
146 hr[m] = hr[m - 1] + (estore[3] - rs[istore])
147 hl[m] = hl[m - 1]
148 for i in range(1, iend + 1):
149 hcomp[i, m] = hcomp[i, m - 1]
150 hd[m] = hp[m] - ht[m] - 8.0
151 j = m - 1
152 # FORMAT 60 holds 5 items: the 10 written make two records
153 for k in (j, m):
154 iounits_mod.write(iounits_mod.ishort,
155 f" OUTER POINT ADDED{k:5d}{hs[k]:15.10f} PTR"
156 f"{hp[k]:10.6f}{ht[k]:10.6f}{hr[k]:10.6f}")
157 lreset = True
158
159 # Flagged points, which the program does not rezone across: the edges of
160 # the central and surface convection zones and of the H shell (Fortran
161 # lines 190–204).
162 iflag = 1
163 if jcore > 1:
164 nflag[iflag] = jcore
165 iflag = iflag + 1
166 if jenv < m and jenv > 1:
167 nflag[iflag] = jenv
168 iflag = iflag + 1
169 # Edge of the H shell
170 if lshell and jxbeg > 1:
171 nflag[iflag] = jxbeg - 1
172 iflag = iflag + 1
173
174 # Flags from the gradients in X, Z and log Omega, at most 100 (Fortran
175 # lines 205–228).
176 too_many = False
177 for i in range(2, m + 1): # loop 120
178 if abs(hcomp[1, i] - hcomp[1, i - 1]) > nmlpar_mod.hpttol[3]:
179 # X gradient
180 nflag[iflag] = i
181 iflag = iflag + 1
182 elif abs(hcomp[3, i] - hcomp[3, i - 1]) > nmlpar_mod.hpttol[4]:
183 # Z gradient
184 nflag[iflag] = i
185 iflag = iflag + 1
186 elif nmlpar_mod.lrot:
187 # gradient in log omega
188 wltop = math.log10(omega[i])
189 wlbot = math.log10(omega[i - 1])
190 if abs(wltop - wlbot) > nmlpar_mod.hpttol[12]:
191 nflag[iflag] = i
192 iflag = iflag + 1
193 if iflag >= 100:
194 iounits_mod.write(iounits_mod.ishort,
195 " MORE THAN 100 FLAG POINTS-FIRST 100 RETAINED")
196 # Question (see the page): this skips the overshoot and
197 # fine-zoning flags below.
198 too_many = True
199 break # GOTO 130
200
201 # The bases of the overshoot region and of the finely zoned region
202 # (Fortran lines 237–293); PMAX1..PMAX5, the largest steps in log P by
203 # region, are computed but read nowhere.
204 if not too_many:
205 pmax1 = nmlpar_mod.hpttol[11] # noqa: F841 (unused in the Fortran too)
206 pmax4 = nmlpar_mod.hpttol[10] # noqa: F841 (unused in the Fortran too)
207 pmax5 = nmlpar_mod.hpttol[8] # noqa: F841 (unused in the Fortran too)
208 if not lc[m]:
209 jos = m
210 jfine = m
211 elif jenv == 1:
212 jos = 1
213 jfine = 1
214 else:
215 # Base of the overshoot region, if any
216 if not nmlpar_mod.lovste:
217 i = jenv
218 jos = jenv
219 else:
220 # Suspected bug (see the page): ALPHAE used as a depth in
221 # log P, not in pressure scale heights.
222 jos = jenv - 1
223 while jos >= 1: # loop 191
224 if hp[jos] - hp[jenv] > nmlpar_mod.alphae:
225 break # GOTO 193
226 jos -= 1
227 jos = jos + 1 # label 193
228 delp = hp[jos] - hp[jenv]
229 if delp > 0.0:
230 np_ = int(delp / nmlpar_mod.hpttol[10])
231 if math.fmod(delp, nmlpar_mod.hpttol[10]) != 0.0:
232 np_ = np_ + 1
233 pmax3 = delp / float(np_) # noqa: F841 (unused in the Fortran too)
234 else:
235 pmax3 = nmlpar_mod.hpttol[10] # noqa: F841 (unused in the Fortran too)
236 if jos > 1:
237 nflag[iflag] = jos
238 iflag = iflag + 1
239 if nmlpar_mod.hpttol[7] == 0.0:
240 jfine = jos
241 elif jos == 1:
242 jfine = 1 # GOTO 198
243 else:
244 # Base of the finely zoned region
245 jfine = jos - 1
246 while jfine >= 1: # loop 195
247 if hp[jfine] - hp[jenv] > nmlpar_mod.hpttol[7]:
248 break # GOTO 197
249 jfine -= 1
250 jfine = jfine + 1 # label 197
251 if jfine != jos:
252 delp = hp[jfine] - hp[jos]
253 np_ = int(delp / nmlpar_mod.hpttol[10])
254 if math.fmod(delp, nmlpar_mod.hpttol[10]) != 0.0:
255 np_ = np_ + 1
256 pmax2 = delp / float(np_)
257 if pmax2 == 0.0:
258 pmax2 = nmlpar_mod.hpttol[10]
259 if jfine > 1:
260 nflag[iflag] = jfine
261 iflag = iflag + 1
262 # label 198
263
264 # Label 130: the last flag is the surface; sort the flags in ascending
265 # order (Fortran lines 294–307).
266 nflag[iflag] = m
267 if iflag != 1:
268 # label 140
269 ldone = False
270 while not ldone:
271 ldone = True
272 for i in range(1, iflag):
273 if nflag[i + 1] < nflag[i]:
274 nflag[i], nflag[i + 1] = nflag[i + 1], nflag[i]
275 ldone = False
276
277 # Remove duplicates (label 160) (Fortran lines 309–320).
278 # Suspected bug (see the page): after a removal i still advances,
279 # so a third equal flag in a row is kept.
280 i = 2
281 while True:
282 if nflag[i] == nflag[i - 1]:
283 if i < iflag:
284 for j in range(i, iflag):
285 nflag[j] = nflag[j + 1]
286 iflag = iflag - 1
287 i = i + 1
288 if not i <= iflag:
289 break
290
291 # Label 180: FORMAT 185 writes 20 flags per record (Fortran lines
292 # 321–323).
293 flags = [nflag[j] for j in range(1, iflag + 1)]
294 for k in range(0, max(len(flags), 1), 20):
295 iounits_mod.write(iounits_mod.ishort, " FLAG-POINTS"
296 + "".join(f"{n:4d}" for n in flags[k:k + 20]))
297
298 # Refloat the points: log Omega into OMEGAL, read nowhere (Fortran lines
299 # 325–333).
300 if nmlpar_mod.lrot:
301 for i in range(1, m + 1): # loop 190
302 if omega[i] > 0.0:
303 omegal[i] = math.log10(omega[i])
304 else:
305 omegal[i] = 0.0
306
307 # The first new point, the saved Teff and surface L, the largest L, and
308 # the tolerances HPMAX (Fortran lines 334–356).
309 oldmod_mod.hss[1] = hs[1]
310 oldmod_mod.hpo[1] = hp[1]
311 oldmod_mod.hlo[1] = hl[1]
312 hko[1] = hcomp[1, 1]
313 hfo[1] = hcomp[3, 1]
314 hlmax = hl[m]
315 # Teff saved (JVS 04/14), and the surface luminosity, HLSURO, for ENTIME
316 oldmod_mod.tefflo = teffl
317 oldmod_mod.hlsuro = hl[m]
318 for i in range(m - 1, 0, -1):
319 if hl[i] > hlmax:
320 hlmax = hl[i]
321 hpmax[1] = nmlpar_mod.hpttol[8]
322 hpmax[2] = nmlpar_mod.hpttol[9] * hlmax
323 hpmax[3] = nmlpar_mod.hpttol[5]
324 hpmax[4] = nmlpar_mod.hpttol[6]
325
326 # Fortran lines 359–361 (IIFLG and I0 are read nowhere).
327 iiflg = 1 # noqa: F841 (unused in the Fortran too)
328 j = 2
329 i0 = 2 # noqa: F841 (unused in the Fortran too)
330
331 # CHI: the running total of normalized differences in m, L, P
332 # (dCHI = dHS/DM + dHL/DL - dHP/DP, the L term only where L increases)
333 # (Fortran lines 364–388).
334 dm = nmlpar_mod.hpttol[2]
335 dl = hpmax[2]
336 chi[1] = 1.0
337 for j in range(2, m + 1):
338 testp = hp[j] - hp[jenv]
339 if abs(testp) < nmlpar_mod.hpttol[7]:
340 dp = nmlpar_mod.hpttol[10] # finely zoned region
341 elif testp > nmlpar_mod.hpttol[7]:
342 dp = nmlpar_mod.hpttol[11] # below the surface convection zone
343 else:
344 dp = nmlpar_mod.hpttol[8] # in the surface convection zone
345 if hl[j] > hl[j - 1]:
346 dchi = ((hs[j] - hs[j - 1]) / dm + (hl[j] - hl[j - 1]) / dl
347 - (hp[j] - hp[j - 1]) / dp)
348 else:
349 dchi = (hs[j] - hs[j - 1]) / dm - (hp[j] - hp[j - 1]) / dp
350 chi[j] = chi[j - 1] + dchi
351
352 # Spline of log m against CHI (Fortran lines 389–394).
353 for j in range(1, m + 1):
354 xtab[j] = chi[j]
355 ytab[j] = hs[j]
356 splinc(xtab, ytab, y2, m)
357
358 # The new points, evenly in CHI between the flags (Fortran lines
359 # 395–421).
360 chiprev = chi[1]
361 jprev = 1
362 mnew = 1
363 for i in range(1, iflag + 1):
364 delchi = chi[nflag[i]] - chiprev
365 npt = int(delchi) + 1
366 if mnew + npt > JSON:
367 # Exceeded the array dimensions: complain and stop
368 print(f" DESIRED NUMBER OF POINTS {mnew + npt:6d}EXCEEEDS JSON "
369 f"{JSON:6d}\n RUN STOPPED")
370 sys.exit(9999)
371 dchi = delchi / float(npt)
372 # Assign the new points, evenly in CHI
373 for j in range(jprev + 1, jprev + npt + 1):
374 x = chiprev + dchi
375 y, klo, khi = splintd2(xtab, ytab, m, y2, x, y, klo, khi)
376 oldmod_mod.hss[j] = y
377 chiprev = x
378 mnew = mnew + npt
379 jprev = mnew
380
381 # Points from the gradient in X: X at the new points, into HKO (Fortran
382 # lines 430–441).
383 for j in range(1, m + 1):
384 xtab[j] = hs[j]
385 ytab[j] = hcomp[1, j]
386 splinc(xtab, ytab, y2, m)
387 for i in range(2, mnew + 1):
388 x = oldmod_mod.hss[i]
389 y, klo, khi = splintd2(xtab, ytab, m, y2, x, y, klo, khi)
390 hko[i] = y
391
392 # Test on the change in X (only where X increases outward); skipped if
393 # HPMAX(3) is zeroed out (Fortran lines 447–483).
394 if hpmax[3] > 1.0e-15:
395 ixx = 0
396 for j in range(mnew, 1, -1):
397 if hko[j] - hko[j - 1] > hpmax[3]:
398 ixx = ixx + 1
399 ixflag[ixx] = j
400 if ixx != 0:
401 mm = mnew
402 for i in range(1, ixx + 1):
403 j = ixflag[i]
404 dx = (hko[j] - hko[j - 1]) / hpmax[3]
405 nn = int(dx) # the number of new points needed
406 if mm + nn > JSON:
407 _stop_insertion("X", mm + nn)
408 dss = ((oldmod_mod.hss[j] - oldmod_mod.hss[j - 1])
409 / float(nn + 1))
410 for k in range(mm + nn, j + nn - 1, -1):
411 oldmod_mod.hss[k] = oldmod_mod.hss[k - nn]
412 for k in range(j + nn - 1, j - 2, -1):
413 oldmod_mod.hss[k] = oldmod_mod.hss[k + 1] - dss
414 mm = mm + nn
415 mnew = mm
416 # label 102
417
418 # Points from the gradient in Z: Z at the new points, into HFO (Fortran
419 # lines 487–499).
420 for j in range(1, m + 1):
421 xtab[j] = hs[j]
422 ytab[j] = hcomp[3, j]
423 splinc(xtab, ytab, y2, m)
424 for i in range(2, mnew + 1):
425 x = oldmod_mod.hss[i]
426 y, klo, khi = splintd2(xtab, ytab, m, y2, x, y, klo, khi)
427 hfo[i] = y
428
429 # Test on the change in Z (only where Z decreases outward); skipped if
430 # HPMAX(4) is zeroed out (Fortran lines 504–539).
431 if hpmax[4] > 1.0e-15:
432 ixx = 0
433 for j in range(mnew, 1, -1):
434 if hfo[j - 1] - hfo[j] > hpmax[4]:
435 ixx = ixx + 1
436 ixflag[ixx] = j
437 if ixx != 0:
438 mm = mnew
439 for i in range(1, ixx + 1):
440 j = ixflag[i]
441 dz = (hfo[j - 1] - hfo[j]) / hpmax[4]
442 nn = int(dz) # the number of new points needed
443 if mm + nn > JSON:
444 _stop_insertion("Z", mm + nn)
445 dss = ((oldmod_mod.hss[j] - oldmod_mod.hss[j - 1])
446 / float(nn + 1))
447 for k in range(mm + nn, j + nn - 1, -1):
448 oldmod_mod.hss[k] = oldmod_mod.hss[k - nn]
449 for k in range(j + nn - 1, j - 2, -1):
450 oldmod_mod.hss[k] = oldmod_mod.hss[k + 1] - dss
451 mm = mm + nn
452 mnew = mm
453 # label 103
454
455 # Delete new points that are too close together (HDO as scratch)
456 # (Fortran lines 542–556).
457 j = 1
458 oldmod_mod.hdo[j] = oldmod_mod.hss[j]
459 for jj in range(2, mnew): # loop 810
460 if oldmod_mod.hss[jj] - oldmod_mod.hdo[j] > nmlpar_mod.hpttol[1]:
461 j = j + 1
462 oldmod_mod.hdo[j] = oldmod_mod.hss[jj]
463 j = j + 1
464 oldmod_mod.hdo[j] = oldmod_mod.hss[mnew]
465 mnew = j
466 for j in range(2, mnew + 1): # loop 820
467 oldmod_mod.hss[j] = oldmod_mod.hdo[j]
468
469 # Outer edge of the convective core and inner edge of the convective
470 # envelope on the new points (Fortran lines 561–576).
471 if jcore > 1:
472 j = 2
473 while j <= mnew: # loop 823
474 if oldmod_mod.hss[j] > hs[jcore]:
475 break # GOTO 824
476 j += 1
477 jcore = j - 1 # label 824
478 else:
479 jcore = 1
480 if jenv < m:
481 j = mnew - 1
482 while j >= 1: # loop 825
483 if oldmod_mod.hss[j] < hs[jenv]:
484 break # GOTO 826
485 j -= 1
486 jenv = j + 1 # label 826
487 else:
488 jenv = mnew
489
490 # The convection flags LC on the new points (Fortran lines 577–597).
491 if jcore > 1:
492 for i in range(1, jcore + 1):
493 lc[i] = True
494 jbeg = jcore + 1
495 else:
496 jbeg = 1
497 if jenv < mnew:
498 for i in range(jenv, mnew + 1):
499 lc[i] = True
500 jend = jenv - 1
501 else:
502 jend = mnew
503 if not (jend < 1 or jbeg > mnew):
504 for j in range(jbeg, jend + 1): # loop 829
505 lc[j] = False
506 # label 830
507
508 # Oscillatory spline of the old run of each variable (on HS, NTAB = M
509 # points) at the new points (HSS, NTOT = MNEW): osplin(xval, yval,
510 # xtab, ytab, ntab, ntot). HPO and HTO serve as scratch (Fortran lines
511 # 602–603).
512 ntab = m
513 ntot = mnew
514
515 def interpolate(arr):
516 # copy the old run into HPO, interpolate into HTO, copy back
517 for j in range(1, m + 1):
518 oldmod_mod.hpo[j] = arr[j]
519 osplin(oldmod_mod.hss, oldmod_mod.hto, hs, oldmod_mod.hpo, ntab, ntot)
520 for j in range(1, mnew + 1):
521 arr[j] = oldmod_mod.hto[j]
522
523 # The entropy terms (7/91) (Fortran lines 614–645).
524 interpolate(entrop_mod.htt0)
525 interpolate(entrop_mod.hpp0)
526 interpolate(entrop_mod.hll0)
527 interpolate(entrop_mod.hrr0)
528
529 # The composition, and HCOMPP, the composition at the start of the step
530 # (needed for composition diffusion in rotating models) (Fortran lines
531 # 648–665).
532 # Question (see the page): is rezoning conservative?
533 for i in range(1, iend + 1):
534 interpolate(hcomp[i])
535 interpolate(oldmod_mod.hcompp[i])
536
537 # The deuterium burning rates, always moved onto the new mesh (Fortran
538 # lines 679–685).
539 interpolate(deuter_mod.drate0)
540
541 # P, R, L, T and rho at the new points (Fortran lines 688–692).
542 osplin(oldmod_mod.hss, oldmod_mod.hpo, hs, hp, ntab, ntot)
543 osplin(oldmod_mod.hss, oldmod_mod.hro, hs, hr, ntab, ntot)
544 osplin(oldmod_mod.hss, oldmod_mod.hlo, hs, hl, ntab, ntot)
545 osplin(oldmod_mod.hss, oldmod_mod.hto, hs, ht, ntab, ntot)
546 osplin(oldmod_mod.hss, oldmod_mod.hdo, hs, hd, ntab, ntot)
547
548 # Rotating models: omega, j/m, fp, ft, r0 and eta2 (Fortran lines
549 # 695–702).
550 if nmlpar_mod.lrot:
551 osplin(oldmod_mod.hss, oldrot_mod.wold, hs, omega, ntab, ntot)
552 osplin(oldmod_mod.hss, oldrot_mod.hjx, hs, hjm, ntab, ntot)
553 osplin(oldmod_mod.hss, fpx, hs, fp, ntab, ntot)
554 osplin(oldmod_mod.hss, ftx, hs, ft, ntab, ntot)
555 osplin(oldmod_mod.hss, oldrot_mod.r0x, hs, r0, ntab, ntot)
556 osplin(oldmod_mod.hss, oldrot_mod.eta2x, hs, eta2, ntab, ntot)
557
558 # The point distribution, if requested (Fortran lines 706–729).
559 if nmlpar_mod.ldebug and nmlpar_mod.npoint < 9999:
560 if model % nmlpar_mod.npoint == 0:
561 idebug = iounits_mod.idebug
562 minmin = min(m, mnew)
563 # FORMAT 910 ('1' starts a new page)
564 iounits_mod.write(idebug, "1" + " " * 20 + "OLD POINTS" + " " * 54
565 + "NEW POINTS\n"
566 + 2 * " N S P T R"
567 " L X Z O16 ")
568 # Suspected bug (see the page): the "old points" columns X, Z and
569 # O16 hold values at the new points.
570 for i in range(1, minmin + 1):
571 iounits_mod.write(idebug, _fmt_row(
572 i, hs[i], hp[i], ht[i], hr[i], hl[i], hko[i], hfo[i],
573 hcomp[9, i]) + _fmt_row(
574 i, oldmod_mod.hss[i], oldmod_mod.hpo[i],
575 oldmod_mod.hto[i], oldmod_mod.hro[i], oldmod_mod.hlo[i],
576 hcomp[1, i],
577 hcomp[3, i], hcomp[9, i]))
578 if m > minmin:
579 minmin = minmin + 1
580 for i in range(minmin, m + 1):
581 iounits_mod.write(idebug, _fmt_row(
582 i, hs[i], hp[i], ht[i], hr[i], hl[i], hko[i],
583 hfo[i], hcomp[9, i]))
584 elif mnew > minmin:
585 minmin = minmin + 1
586 for i in range(minmin, mnew + 1):
587 iounits_mod.write(idebug, " " * 64 + _fmt_row(
588 i, oldmod_mod.hss[i], oldmod_mod.hpo[i],
589 oldmod_mod.hto[i], oldmod_mod.hro[i],
590 oldmod_mod.hlo[i],
591 hcomp[1, i], hcomp[3, i], hcomp[9, i]))
592
593 # Transfer the new points (Fortran lines 733–750).
594 for j in range(1, mnew + 1):
595 hs[j] = oldmod_mod.hss[j]
596 hp[j] = oldmod_mod.hpo[j]
597 ht[j] = oldmod_mod.hto[j]
598 hr[j] = oldmod_mod.hro[j]
599 hl[j] = oldmod_mod.hlo[j]
600 hd[j] = oldmod_mod.hdo[j]
601 if nmlpar_mod.lrot:
602 for j in range(1, mnew + 1): # loop 1005
603 hjm[j] = oldrot_mod.hjx[j]
604 omega[j] = oldrot_mod.wold[j]
605 fp[j] = fpx[j]
606 ft[j] = ftx[j]
607 eta2[j] = oldrot_mod.eta2x[j]
608 r0[j] = oldrot_mod.r0x[j]
609
610 # The energy generation at the start of the step (MHP 6/00) (Fortran
611 # lines 752–758).
612 # Suspected bug (see the page): HS already holds the new points here
613 # (loop 1000), while SESUM and SEG are on the old ones.
614 if nmlpar_mod.lrot or (nmlpar_mod.lexcom and nmlpar_mod.lovste):
615 osplin(oldmod_mod.hss, oldphy_mod.esumo, hs, scrtch_mod.sesum, ntab,
616 ntot)
617 for im in range(1, m + 1):
618 ytab[im] = (scrtch_mod.sesum[im] + scrtch_mod.seg[6, im]
619 + scrtch_mod.seg[7, im])
620 osplin(oldmod_mod.hss, oldphy_mod.epso, hs, ytab, ntab, ntot)
621
622 # Fortran lines 759–761.
623 iounits_mod.write(iounits_mod.ishort, f" POINTS OLD{m:5d} NEW{mnew:5d}")
624 m = mnew
625
626 # Masses: HS1 = m at each point, HS2 = the mass of each shell (Fortran
627 # lines 763–773).
628 clndp = constants_mod.clndp
629 ds3 = math.exp(clndp * hs[1])
630 ds2 = -ds3
631 for i in range(2, m + 1): # loop 1030
632 ds1 = ds2
633 ds2 = ds3
634 ds3 = math.exp(clndp * hs[i])
635 hs1[i - 1] = ds2
636 hs2[i - 1] = 0.5 * (ds3 - ds1)
637 hs1[m] = ds3
638 hs2[m] = math.exp(constants_mod.cln * hstot) - 0.5 * (ds2 + ds3)
639
640 if nmlpar_mod.lrot:
641 # First guess of the moment of inertia (Fortran lines 776–778).
642 for i in range(1, m + 1):
643 hi[i] = constants_mod.cc23 * hs2[i] * math.exp(
644 constants_mod.cln * 2.0 * hr[i])
645
646 # Overshoot (Fortran lines 780–781).
647 nrzone, nzone = ovrot(hcomp, hd, hp, hr, hs, ht, lc, m, lcz, mrzone,
648 mxzone, 0, 0)
649
650 # The moment of inertia again, on the new points, before the
651 # rotation (JNT 2025/09/03) (Fortran line 786).
652 # Question (see the page): is this extra call still needed?
653 momi(eta2, hr, hs, hs2, 1, m, omega, r0, hi, qiw)
654
655 # Omega from the specific angular momentum HJM (Fortran line 791).
656 getrot(hd, hjm, hr, hs, hs2, lcz, m, eta2, hi, omega, qiw, r0)
657
658 # fp, ft, r0 and eta2 from omega (Fortran line 793).
659 fpft(hd, hr, hs, m, omega, eta2, fp, ft, hg, r0)
660
661 # The moment of inertia (Fortran line 796).
662 momi(eta2, hr, hs, hs2, 1, m, omega, r0, hi, qiw)
663
664 # The new total angular momentum and rotational kinetic energy
665 # (Fortran lines 798–811).
666 sumj = 0.0
667 sumke = 0.0
668 for i in range(1, m + 1): # loop 1110
669 hj = hjm[i] * hs2[i]
670 hkerot[i] = 0.5 * omega[i] * hj
671 sumj = sumj + hj
672 sumke = sumke + hkerot[i]
673 iounits_mod.write(iounits_mod.ishort,
674 f" TOTAL J OF STAR - PREVIOUS {sjtot:21.13E} NEW "
675 f"{sumj:21.13E}\n TOTAL ROTATIONAL K.E. OF STAR-"
676 f"PREVIOUS {skerot:21.13E} NEW {sumke:21.13E}")
677 sjtot = sumj
678 skerot = sumke
679
680 # Store the old model structure for use in diffusion (Fortran lines
681 # 813–823).
682 for i in range(1, m + 1):
683 oldrot_mod.wold[i] = omega[i]
684 oldrot_mod.hgo[i] = hg[i]
685 oldrot_mod.hio[i] = hi[i]
686 oldrot_mod.eta2x[i] = eta2[i]
687 oldrot_mod.r0x[i] = r0[i]
688 oldmod_mod.lco[i] = lc[i]
689 oldmod_mod.lczo[i] = lcz[i]
690 oldrot_mod.hjx[i] = hjm[i]
691
692 # The physics at the new points: for rotation, or for light elements
693 # with envelope overshoot (to locate the base of the overshoot region)
694 # (Fortran lines 828–834).
695 if nmlpar_mod.lrot or (nmlpar_mod.lexcom and nmlpar_mod.lovste):
696 physic(fp, ft, hcomp, hd, hg, hl, hp, hr, hs, ht, lc, m, teffl, cmixl)
697
698 # Store what diffusion needs at the start of the step (Fortran lines
699 # 839–856).
700 for im in range(1, m + 1):
701 oldphy_mod.delro[im] = scrtch_mod.sdel[1, im]
702 oldphy_mod.delo[im] = scrtch_mod.sdel[2, im]
703 oldphy_mod.delao[im] = scrtch_mod.sdel[3, im]
704 oldphy_mod.amuo[im] = temp_mod.hamu[im]
705 oldphy_mod.oo[im] = scrtch_mod.so[im]
706 oldphy_mod.cpo[im] = temp_mod.cp[im]
707 oldphy_mod.qdto[im] = temp_mod.sqdt[im]
708 oldphy_mod.velo[im] = scrtch_mod.svel[im]
709 oldphy_mod.visco[im] = temp_mod.visc[im]
710 oldphy_mod.thdifo[im] = temp_mod.thdif[im]
711 dwmax_mod.qwrmx0[im] = dwmax_mod.qwrmax[im]
712
713 # The time evolution of the angular velocity (MHP 06/02) (Fortran
714 # lines 859–867).
715 cln = constants_mod.cln
716 for i in range(2, m + 1):
717 dr = math.exp(cln * hr[i]) - math.exp(cln * hr[i - 1])
718 dw = omega[i] - omega[i - 1]
719 wmid = 0.5 * (omega[i] + omega[i - 1])
720 fac = (2.0 * (hr[i] + hr[i - 1]) - 0.5 * (hs[i] + hs[i - 1])
721 - constants_mod.cgl)
722 oldrot2_mod.tho[i] = math.exp(cln * fac) * wmid * dw / dr
723 oldrot2_mod.qwrst[i] = dw / dr
724
725 # A new surface opacity table, if needed (Fortran lines 870–875).
726 if abs(comp_mod.xnew - hcomp[1, m]) > 1.0e-8:
727 comp_mod.xnew = hcomp[1, m]
728 comp_mod.znew = hcomp[3, m]
729 surfopac(comp_mod.xnew)
730
731 return m, lreset, jcore, jenv, sjtot, skerot