1
2C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
3C RSCALE
4C$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
5 SUBROUTINE RSCALE(HL,HCOMP,HS,HSTOT,M,NK,SMASS,LC)
6C 10/15/26 MHP via Claude
7C code changed to take JSON from DIMENSIONS_MOD instead of declaring
8C PARAMETER(JSON=5000) here.
9 USE DIMENSIONS_MOD
10C 10/14/26 MHP via Claude
11C code changed to convert COMMON/LABEL/ into LABEL_MOD.
12 USE LABEL_MOD
13C 10/14/26 MHP via Claude
14C code changed to convert COMMON/COMP/ into COMP_MOD.
15 USE COMP_MOD
16C 10/14/26 MHP via Claude
17C code changed to convert COMMON/NMLPAR/ into NMLPAR_MOD.
18 USE NMLPAR_MOD
19C 10/14/26 MHP via Claude
20C code changed to convert COMMON/CONSTANTS/ into CONSTANTS_MOD.
21 USE CONSTANTS_MOD
22C 10/14/26 MHP via Claude
23C code changed to convert COMMON/IOUNITS/ into IOUNITS_MOD.
24 USE IOUNITS_MOD
25C 10/14/26 MHP via Claude
26C code changed to convert COMMON/RUNLOOP/ into RUNLOOP_MOD. A blanket
27C USE imports exactly the names the COMMON declaration made global here,
28C so it cannot change meaning. See runloop_mod.f for the block history
29C and for why the module declares the types the implicit rules supplied.
30 USE RUNLOOP_MOD
31C 10/20/26 MHP via Claude
32C code changed to replace implicit typing with IMPLICIT NONE and
33C explicit declarations.
34 IMPLICIT NONE
35 REAL*8 CHKENV,CORNEW,COROLD,DCOR,DELZ,DENV,ENVNEW,ENVOLD,ENVOLD2,
36 * * ENVTOTAL,FS,HCOMP,HL,HS,HSTOT,HSTOT1,SFACTOR,SHIFT,SHLNEW,
37 * * SHLOLD,SHLP,SLOPE,SMASS,TEMP,XFACT,XTARG,ZFACT,ZP
38 INTEGER I,I1,ICOMP,J,JCORE,JENV,JXBEG,JXEND,JXMID,M,NK
39 LOGICAL*4 LC,LSHELL
40C DBG 5/94 Added rescaling of Z in core ZRAMP stuff.
41C CHARACTER*256 FLAOL2, FOPAL2
42C 9/25/26 MHP via Claude
43C code changed to consolidate all I/O logical unit numbers, previously
44C scattered across COMMON/LUOUT/, COMMON/LUNUM/, COMMON/ALEX06/,
45C COMMON/ACDPTH/, COMMON/NEWOPAC/, COMMON/LOPAL95/, COMMON/ATMOS2/,
46C COMMON/ALATM03/, COMMON/OPALEOS/, and COMMON/SCV2/, into a single
47C COMMON/IOUNITS/
48C 10/12/26 MHP via Claude
49C code changed to extend COMMON/NMLPAR/ to 234 members, adding the
50C namelist variables that the physics routines read from 27 COMMON
51C blocks which also held derived or working members. Those blocks keep
52C only their non-namelist members; five of them -- NEWMX, VMULT,
53C PMMWIND, CCOUT1 and ENVGEN -- had nothing left and are gone.
54C Derivation-only namelist variables from the same blocks went to
55C COMMON/NMLBYPASS/ instead, not here.
56C
57C Declared identically in all 121 files that hold any of these members.
58C Generated from one member list, so every copy is byte-identical; the
59C linker's 'size of symbol changed' warning is the check that they are.
60C MHP 5/91 COMMON BLOCK ADDED TO FIX CORE RESCALING.
61C 9/25/26 MHP via Claude
62C code changed to merge COMMON/CONST/, COMMON/CONST1/, COMMON/CONST2/,
63C and COMMON/CONST3/ into a single COMMON/CONSTANTS/
64c ISETMIX,ISETISO,
65c * LMIXTURE,LISOTOPE,FRAC_C,FRAC_N,FRAC_O,R12_13,R14_15,R16_17,R16_18,ZXMIX,
66c * XH2_INI,XHE3_INI,XLI6_INI,XLI7_INI,XBE9_INI,XB10_INI,XB11_INI
67C COMMON/NEWCMP/XNEWCP,INEWCP,LNEWCP,LREL,ANEWCP
68C MHP 8/25 Removed character file names from common block
69C DBG 5/94 ZRAMP stuff.
70C 9/24/26 MHP via Claude
71C code changed to remove dead IOOPAL2 from COMMON/ZRAMP/
72C 10/9/26 MHP via Claude
73C code changed to remove NK (was NK2 here only, since this file's own
74C dummy argument NK already carries the identical value, passed down
75C from main.f's own run-index loop variable through STARIN) from
76C COMMON/ZRAMP/. It was never read by name here, only declared for
77C positional alignment with the other members, so this file's own NK
78C argument is untouched.
79C 10/13/26 MHP via Claude
80C code changed to remove COMMON/ZRAMP/: its sole remaining member
81C IOLAOL2 is neither written nor read anywhere. The namelist members
82C that shared this block moved to the consolidated block in stage 2b.
83 DIMENSION HCOMP(15,JSON),HS(JSON),HL(JSON),LC(JSON)
84 SAVE
85
86c ************
87c write(*,*)
88c write(*,*)'Entering rscale ',HSTOT-HS(M)
89c ************
90
91 IF(RESCAL(2,NK).GT.0.0D0) THEN
92C RESCALE X BY MULTIPLYING ALL SHELL X VALUES BY THE RATIO (XNEW/XOLD)
93C WHERE XOLD = OLD SURFACE X VALUE
94C THIS METHOD OK FOR BOTH HORIZONTAL BRANCH AND MAIN SEQUENCE STARS
95 IF(RESCAL(2,NK).LE.1.0D0) THEN
96 XFACT = RESCAL(2,NK)/DMAX1(XNEW,1.0D-20)
97 DO 10 I = 1,M
98 HCOMP(1,I) = DMIN1(RESCAL(2,NK),HCOMP(1,I)*XFACT)
99 10 10 CONTINUE
100 XNEW = RESCAL(2,NK)
101 XENV0 = RESCAL(2,NK)
102C DBG 4/95 BUG FIX XENV IS USED IN SOME ROUTINES AND NOT XENV0 SO CHANGE
103C XENV WHENEVER X IS CHANGED.
104C MHP 7/99 THIS IS NOT A BUG, IT IS NECESSARY.
105C XENV IS USED TO SET THE INITIAL MU FOR THE YALE EQUATION OF STATE,
106C AND IT SHOULD NOT BE CHANGED AFTER THE FIRST RUN.
107C XENV = XENV0
108 ELSE
109C DESIRED X >100%; X NOT CHANGED
110C ACOMP = ' X '
111 I1 = 2
112 WRITE(ISHORT,1000)NK,RESCAL(I1,NK)
113 1000 1000 FORMAT(1X,'ERROR IN SUBROUTINE RSCALE'/1X,'RESCALING OF X',
114 * * ' IN KIND CARD #',I3,1X,'FAILED - DESIRED COMP',F9.6/1X,
115 * * 'GREATER THAN UNITY. X NOT RESCALED')
116 ENDIF
117 ENDIF
118C 10/30/26 MHP via Claude
119C code changed from .GE. to .GT., as for X and the mass. RSCLZ defaults
120C to 0, so a rescale card that left Z unset set Z = 0. No deck asks
121C for Z = 0, which the opacity tables do not cover in any case.
122 IF(RESCAL(3,NK).GT.0.0D0) THEN
123C RESCALE Z BY ADDING (RESCAL(3,NK)-OLD Z) TO EACH Z VALUE IN THE STAR
124C THE CNO CYCLE ELEMENTS AND HE3 ARE MULTIPLIED BY THE RATIO OF THE
125C DESIRED NEW Z TO THE OLD Z - LIGHT ELEMENT ABUNDANCES ARE LEFT ALONE
126 IF(RESCAL(3,NK).LE.1.0D0) THEN
127 DELZ = RESCAL(3,NK) - ZNEW
128 DO 30 J = 1,M
129 ZFACT=DMAX1(0.D0,HCOMP(3,J)+DELZ)/(HCOMP(3,J)+1.D-30)
130 HCOMP(3,J) = DMAX1(0.0D0,HCOMP(3,J)+DELZ)
131 DO 20 I = 5,11
132 HCOMP(I,J) = HCOMP(I,J)*ZFACT
133 20 20 CONTINUE
134 30 30 CONTINUE
135 ZNEW = RESCAL(3,NK)
136 ZENV0 = RESCAL(3,NK)
137C DBG 4/95 BUG FIX ZENV IS USED IN MANY ROUTINES AND NOT ZENV0 SO CHANGE
138C ZENV WHENEVER Z IS CHANGED.
139 ZENV = ZENV0
140 ELSE
141C DESIRED Z >100%; Z NOT CHANGED
142C ACOMP = ' Z '
143 I1 = 3
144 WRITE(ISHORT,1002)NK,RESCAL(I1,NK)
145 1002 1002 FORMAT(1X,'ERROR IN SUBROUTINE RSCALE'/1X,'RESCALING OF Z',
146 * * ' IN KIND CARD #',I3,1X,'FAILED - DESIRED COMP',F9.6/1X,
147 * * 'GREATER THAN UNITY. Z NOT RESCALED')
148 ENDIF
149 ENDIF
150 IF(HCOMP(1,1).GT.1.0D-10) THEN
151c ************
152c write(*,*)'Entering MS change ',HSTOT-HS(M)
153c ************
154
155C MAIN SEQUENCE RESCALING - MASS AND SINGLE ELEMENT.
156 IF(LNEWCP.AND.XNEWCP.GE.0.0D0) THEN
157C RESCALE THE ABUNDANCE OF ONE ELEMENT OTHER THAN X,Y,Z
158C JNEWCP = INDEX OF ELEMENT TO BE CHANGED IN MATRIX HCOMP
159C IF LREL = T, ABUNDANCE IS RELATIVE TO SURFACE HYDROGEN ABUNDANCE
160C ON A LOGARITHMIC SCALE WHERE X ABUNDANCE = 12.0
161C E.G. AN ABUNDANCE OF 3.0 MEANS 1.0D-9* SURFACE H ABUNDANCE
162C 10/30/26 MHP via Claude
163C code changed to convert a relative target into a local, XTARG. It
164C used to overwrite the control XNEWCP, so a second rescale converted
165C the converted value again (10**(~0-12) X, about 1e-12 X).
166 XTARG = XNEWCP
167 IF(LREL) XTARG = DEXP(CLN*(XNEWCP-12.0D0))*HCOMP(1,M)
168 IF(XTARG.LT.1.0D0) THEN
169 DO 35 I = 1,M
170 HCOMP(INEWCP,I) = XTARG
171 35 35 CONTINUE
172 ELSE
173C ERROR - RESCALED ABUNDANCE >100% - ABUNDANCE NOT CHANGED
174C ACOMP = ANEWCP
175 WRITE(ISHORT,1004)ICOMP,NK,XTARG
176 1004 1004 FORMAT(1X,'ERROR IN SUBROUTINE RSCALE'/1X,'RESCALING OF ',
177 * * 'SPECIES ',I3,' IN KIND CARD # ',I3,' FAILED - DESIRED COMP',F9.6/1X,
178 * * 'GREATER THAN UNITY. Z NOT RESCALED')
179 ENDIF
180 ENDIF
181C RESCALE STAR MASS BY MULTIPLYING ALL MASS POINTS IN THE STAR BY
182C A SCALE FACTOR(MNEW/MOLD) WHILE LEAVING ALL OTHER LOCAL VARIABLES
183C UNCHANGED.
184 IF(RESCAL(1,NK).GT.0.0D0) THEN
185 HSTOT1 = DLOG10(RESCAL(1,NK)/SMASS)
186 HSTOT = HSTOT + HSTOT1
187 SMASS = RESCAL(1,NK)
188 STOTAL = HSTOT
189 DO 40 I = 1,M
190 HS(I) = HS(I) + HSTOT1
191 40 40 CONTINUE
192 ENDIF
193 ELSE
194C HORIZONTAL BRANCH RESCALING;CORE MASS AND TOTAL MASS.
195C FOR TOTAL MASS,TREAT AS MAIN SEQUENCE BUT ONLY CHANGE
196C THE MASS POINTS OUTSIDE THE H-BURNING SHELL;
197C FOR CORE MASS CHANGE THE POINTS INSIDE THE H-BURNING
198C SHELL AND CORRESPONDINGLY REDUCE/INCREASE THE MASS OUTSIDE
199C THE SHELL.
200c ************
201c write(*,*)'Entering HB scale ',HSTOT-HS(M)
202c ************
203
204
205 IF(RESCAL(1,NK).GT.0.0D0.OR.RESCAL(4,NK).GT.0.0D0) THEN
206C RESCALE MASS AND/OR CORE MASS
207C FIND H-BURNING SHELL.
208C
209
210C ************* Added call to FINDSHELL (gn - 10/05)**************
211
212 CALL FINDSH(HCOMP,HL,LC,M,JCORE,JENV,JXBEG,JXEND,JXMID,
213 * * LSHELL)
214C ****************************************************************
215
216C FIND CORE, ENVELOPE, AND H-BURNING SHELL MASSES.
217 COROLD = EXP(CLN*HS(JXBEG-1))/CMSUN
218 ENVOLD = (EXP(CLN*HSTOT)-EXP(CLN*HS(JXEND)))/CMSUN
219 ENVOLD2 = (EXP(CLN*HS(M))-EXP(CLN*HS(JXEND)))/CMSUN
220 SHLOLD = (EXP(CLN*HS(JXEND))-EXP(CLN*HS(JXBEG-1)))/CMSUN
221 DENV = 0.0D0
222 DCOR = 0.0D0
223 WRITE(ISHORT,63)COROLD,SHLOLD,ENVOLD,SMASS
224 63 63 FORMAT(1X,'HB-OLD MASSES: CORE ',
225 * * F9.6,' SHELL ',F9.6,' ENV ',F9.6,' TOTAL',F9.6)
226 ENDIF
227
228 IF(RESCAL(1,NK).GT.0.0D0) THEN
229
230C MASS RESCALING : ADD OR SUBTRACT MASS FROM THE ENVELOPE OUTSIDE
231C THE H-BURNING SHELL (ONLY).
232C
233C ENSURE THAT THE NEW ENVELOPE MASS IS POSITIVE.
234
235
236 DENV = RESCAL(1,NK) - SMASS
237 ENVNEW = ENVOLD + DENV
238
239c ** Reduce either total mass outside core OR the standard envelope only ***
240 IF((((10D0**HSTOT)/CMSUN)-COROLD).GE.0.01D0) THEN
241c ************
242 write(*,*)'Entering old method ',(10**HSTOT-10**HS(M))/
243 * * (10**HS(M)-10**HS(JXBEG-1))
244 write(*,*)'SENV ',10**HSTOT - 10**HS(M)
245 write(*,*)'Envelope ',10**HS(M) - 10**HS(JXBEG-1)
246c ************
247
248c **************************************************************************
249c write(*,*)JXBEG-1,JXMID,JXEND,M
250 IF(ENVNEW.LE.0.0D0)THEN
251 WRITE(ISHORT,69)ENVOLD,ENVOLD+DENV,RESCAL(1,NK),SMASS
252 69 69 FORMAT(1X,'ERROR IN SUBROUTINE RSCALE'/1X,
253 * * 'DESIRED NEW ENVELOPE MASS LESS THAN ZERO'/1X,
254 * * 'OLD ENVELOPE MASS ',1PE9.2,' NEW ENVELOPE ',E9.2,
255 * * ' NEW AND OLD TOTAL MASS ',2E10.2)
256C 10/30/26 MHP via Claude: bare STOP -> STOP 1, the run-time error code (issue 38).
257 STOP 1
258 ENDIF
259
260c ***** Calculate scale factor for mass rescaling *****
261
262c HSTOT1 = DLOG10(RESCAL(1,NK)/SMASS)
263 SFACTOR =(RESCAL(1,NK)-EXP(CLN*HS(JXEND))/CMSUN)/
264 * * (SMASS-EXP(CLN*HS(JXEND))/CMSUN)
265
266c *****************************************************
267
268c HSTOT = HSTOT + HSTOT1
269 HSTOT=DLOG10(10**HS(JXEND)+SFACTOR*(10**HSTOT-10**HS(JXEND)))
270
271 SMASS = RESCAL(1,NK)
272 STOTAL = HSTOT
273 DO 70 I = JXEND+1,M
274 HS(I)=DLOG10(10**HS(JXEND)+SFACTOR*(10**HS(I)-10**HS(JXEND)))
275 70 70 CONTINUE
276 ENVOLD = ENVNEW
277c *****
278c write(*,*)'Mass difference ',DENV
279c write(*,*)'HSTOT1 ',HSTOT1
280c write(*,*)'SFACTOR ',DLOG10(SFACTOR)
281c ************
282c write(*,*)'leaving old method ',HSTOT-HS(M)
283c ************
284
285 ELSE
286
287c ************
288 write(*,*)'Entering new method ',(10**HSTOT-10**HS(M))/
289 * * (10**HS(M)-10**HS(JXBEG-1))
290 write(*,*)'SENV ',10**HSTOT - 10**HS(M)
291 write(*,*)'Envelope ',10**HS(M) - 10**HS(JXBEG-1)
292c ************
293c *** print debug info ***
294c write(*,*)JXBEG-1,JXMID,JXEND,M
295c write(*,*)(10**HS(JXBEG-1))/CMSUN,' core'
296c write(*,*)(10**HS(JXMID))/CMSUN,' mid'
297c write(*,*)(10**HS(JXEND))/CMSUN,' end'
298c write(*,*)(10**HS(M))/CMSUN,' M'
299c write(*,*)(10**HSTOT)/CMSUN,' total'
300 CHKENV = ((10**HSTOT)/CMSUN)-COROLD
301 IF(CHKENV.LE.0.0D0)THEN
302 WRITE(ISHORT,69)ENVOLD,ENVOLD+DENV,RESCAL(1,NK),SMASS
303C 10/30/26 MHP via Claude: bare STOP -> STOP 1, the run-time error code (issue 38).
304 STOP 1
305 ENDIF
306
307c **** Calculate scale factor *****
308
309c HSTOT1 = DLOG10(RESCAL(1,NK)/SMASS)
310 SFACTOR =(RESCAL(1,NK)-EXP(CLN*HS(JXBEG-1))/CMSUN)/
311 * * (SMASS-EXP(CLN*HS(JXBEG-1))/CMSUN)
312c write(*,*)'hstot1',(10**HSTOT1)
313c write(*,*)'smass',SMASS
314
315c HSTOT = HSTOT + HSTOT1
316 HSTOT=DLOG10(10**HS(JXBEG-1)+SFACTOR*(10**HSTOT-10**HS(JXBEG-1)))
317
318 SMASS = RESCAL(1,NK)
319 STOTAL = HSTOT
320 DO 78 I = JXBEG,M
321 HS(I)=DLOG10(10**HS(JXBEG-1)+SFACTOR*(10**HS(I)-10**HS(JXBEG-1)))
322 78 78 CONTINUE
323 ENVOLD = (EXP(CLN*HSTOT)-EXP(CLN*HS(JXEND)))/CMSUN
324 ENVTOTAL=(EXP(CLN*HS(M))-EXP(CLN*HS(JXBEG-1)))/CMSUN
325c write(*,*)'total envelope ',ENVTOTAL
326c write(*,*)'HSTOT1 ',HSTOT1
327c write(*,*)'SFACTOR ',DLOG10(SFACTOR)
328
329c ************
330c write(*,*)'leaving new method ',HSTOT-HS(M)
331c ************
332
333 ENDIF
334 ENDIF
335c ******************************************************************
336
337 IF(RESCAL(4,NK).GT.0.0D0) THEN
338
339C RESCALE CORE MASS.
340C THE MASS OF THE H-BURNING SHELL IS HELD FIXED, AND MASS IS TRANSFERRED
341C FROM THE CORE TO THE ENVELOPE (OR VICE VERSA).
342C
343
344 SHLP= (EXP(CLN*HS(JXEND)))
345 DCOR = RESCAL(4,NK) - COROLD
346 DENV = - DCOR
347 ENVNEW = ENVOLD2 + DENV
348 IF(ENVNEW.LE.0.0D0)THEN
349 WRITE(ISHORT,71)ENVOLD,ENVNEW,RESCAL(4,NK),COROLD
350 71 71 FORMAT(1X,'ERROR IN SUBROUTINE RSCALE'/1X,
351 * * 'NEW ENVELOPE MASS LESS THAN ZERO BECAUSE OF CORE',
352 * * ' RESCALING'/1X,
353 * * 'OLD ENVELOPE MASS ',1PE10.2,' NEW ENVELOPE ',E10.2,
354 * * ' NEW AND OLD CORE MASS ',2E10.2)
355C 10/30/26 MHP via Claude: bare STOP -> STOP 1, the run-time error code (issue 38).
356 STOP 1
357 ENDIF
358 HSTOT1 = DLOG10(RESCAL(4,NK)/COROLD)
359 DO 80 I = 1,JXBEG-1
360 HS(I) = HS(I) + HSTOT1
361 80 80 CONTINUE
362
363C HOLD H-SHELL MASS CONSTANT;SHIFT IS THE CHANGE IN THE
364C UNLOGGED MASS OF EACH POINT IN THE H SHELL.
365 SHIFT = DCOR*CMSUN
366 DO 90 I = JXBEG,JXEND
367 TEMP = EXP(CLN*HS(I))
368 HS(I) = LOG10(TEMP + SHIFT)
369 90 90 CONTINUE
370C NOW SHRINK OR EXPAND THE ENVELOPE MASS TO RETAIN TOTAL CONSTANT MASS.
371C
372
373 SFACTOR =(EXP(CLN*HS(M))-EXP(CLN*HS(JXEND)))/
374 * * (EXP(CLN*HS(M))-SHLP)
375
376 DO 100 I = JXEND+1,M
377 HS(I)=DLOG10(10**HS(M)-SFACTOR*(10**HS(M)-10**HS(I)))
378 100 100 CONTINUE
379
380 ENDIF
381
382 IF(RESCAL(1,NK).GT.0.0D0.OR.RESCAL(4,NK).GT.0.0D0)THEN
383 CORNEW = EXP(CLN*HS(JXBEG-1))/CMSUN
384 ENVNEW = (EXP(CLN*HSTOT)-EXP(CLN*HS(JXEND)))/CMSUN
385 SHLNEW = (EXP(CLN*HS(JXEND))-EXP(CLN*HS(JXBEG-1)))/CMSUN
386 WRITE(ISHORT,101)CORNEW,SHLNEW,ENVNEW,SMASS
387 101 101 FORMAT(1X,'HB-RESCALED MASSES: CORE ',
388 * * F9.6,' SHELL ',F9.6,' ENV ',F9.6,' TOTAL ',F9.6)
389
390 ENDIF
391 ENDIF
392C CHANGE Y TO REFLECT NEW X,Z, AND HE3 VALUES.
393 DO 110 I = 1,M
394 HCOMP(2,I) = 1.0D0-HCOMP(1,I)-HCOMP(3,I)-HCOMP(4,I)
395 110 110 CONTINUE
396C
397C DBG 5/94 rescale interior Z if LZRAMP flag is T.
398C Z is linearly adjusted from RSCLZC at the center to surface Z at
399C mass fraction RSCLZM. Compensate changing Z with X.
400 IF(LZRAMP.AND.(RSCLZC(NK).GT.0D0).AND.(RSCLZM1(NK).GT.0D0)
401 * * .AND.(RSCLZM2(NK).GT.0D0))THEN
402 SLOPE = (ZNEW - RSCLZC(NK))/(RSCLZM2(NK)-RSCLZM1(NK))
403 DO I = 1,M
404 FS = 10.0D0**HS(I)/(SMASS*CMSUN)
405 IF (FS .LT. RSCLZM1(NK)) THEN
406C 10/30/26 MHP via Claude
407C code changed to scale CNO by Z_new/Z_old, as the uniform rescale does.
408C (Z_old-Z_new)/Z_old was right only when Z halves; it gave 0 for no
409C change and a negative abundance when Z rose.
410 ZFACT = RSCLZC(NK)/(HCOMP(3,I)+1.0D-30)
411 HCOMP(3,I) = RSCLZC(NK)
412 HCOMP(1, I) = 1.0D0-HCOMP(3,I)-HCOMP(4,I)-HCOMP(2,I)
413 DO J = 5,11
414 HCOMP(J,I) = HCOMP(J,I)*ZFACT
415 ENDDO
416 ELSE IF (FS .LT. RSCLZM2(NK)) THEN
417 ZP = (FS-RSCLZM1(NK))*SLOPE+RSCLZC(NK)
418 ZFACT = ZP/(HCOMP(3,I)+1.0D-30)
419 HCOMP(3, I) = ZP
420 HCOMP(1, I) = 1.0D0-HCOMP(3,I)-HCOMP(4,I)-HCOMP(2,I)
421 DO J = 5,11
422 HCOMP(J,I) = HCOMP(J,I)*ZFACT
423 ENDDO
424 END IF
425 ENDDO
426 END IF
427c ************
428c write(*,*)'Leaving rscale ',HSTOT-HS(M)
429c ************
430c IF(HSTOT.LT.HS(M)) STOP
431 RETURN
432 END
1"""Python version of rscale.f (YREC 7be4133): rescaling a starting model
2as a kind card asks (X, Z, one species, the total mass, the core mass of a
3horizontal-branch star), and the ZRAMP option."""
4
5import math
6import numpy as np
7
8from pyrec import comp_mod
9from pyrec import constants_mod
10from pyrec import iounits_mod
11from pyrec import label_mod
12from pyrec import nmlpar_mod
13from pyrec import runloop_mod
14from pyrec.findsh import findsh
15
16
17def _error_stop(text_lines: list[str]) -> None:
18 """Write an error message to ISHORT and stop the run."""
19
20 for line in text_lines:
21 iounits_mod.write(iounits_mod.ishort, line)
22 raise SystemExit(1)
23
24
25def rscale(hl: np.ndarray, hcomp: np.ndarray, hs: np.ndarray, hstot: float, m: int, nk: int, smass: float,
26 lc: np.ndarray) -> tuple[float, float]:
27 """Rescale the model for kind card nk: X, Z, one species (main
28 sequence), the total mass (main sequence: every mass point scaled;
29 horizontal branch: the mass coordinate stretched above the hydrogen
30 shell or its base) and the core mass (horizontal branch); then reset Y
31 and apply ZRAMP. The targets are runloop_mod.rescal[1..4, nk], the
32 species nmlpar_mod.xnewcp, inewcp, and the ramp nmlpar_mod.rsclzc,
33 rsclzm1, rsclzm2.
34
35 Translates: rscale.f#RSCALE (7be4133)
36
37 Arguments: hl, hcomp, hs (changed in place), hstot (log total mass),
38 m, nk, smass (total mass in solar masses), lc. Also sets comp_mod.xnew,
39 znew, zenv, stotal and label_mod.xenv0, zenv0. Returns (hstot, smass).
40
41 """
42
43 c = constants_mod
44 comp = comp_mod
45 nml = nmlpar_mod
46 rescal = runloop_mod.rescal
47 w = iounits_mod.write
48 ishort = iounits_mod.ishort
49
50 # X: every shell scaled by X_new / X_surf, capped at X_new (Fortran lines 91–117).
51 if rescal[2, nk] > 0.0:
52 if rescal[2, nk] <= 1.0:
53 xfact = rescal[2, nk] / max(comp.xnew, 1.0e-20)
54 for i in range(1, m + 1):
55 hcomp[1, i] = min(rescal[2, nk], hcomp[1, i] * xfact)
56 comp.xnew = rescal[2, nk]
57 label_mod.xenv0 = rescal[2, nk]
58 else:
59 i1 = 2
60 w(ishort, " ERROR IN SUBROUTINE RSCALE") # format 1000
61 w(ishort, f" RESCALING OF X IN KIND CARD #{nk:3d} FAILED - "
62 f"DESIRED COMP{rescal[i1, nk]:9.6f}")
63 w(ishort, " GREATER THAN UNITY. X NOT RESCALED")
64
65 # Z: the same amount added in every shell; species 5-11 scaled (Fortran lines 122–149).
66 if rescal[3, nk] > 0.0:
67 if rescal[3, nk] <= 1.0:
68 delz = rescal[3, nk] - comp.znew
69 for j in range(1, m + 1):
70 zfact = max(0.0, hcomp[3, j] + delz) / (hcomp[3, j] + 1.0e-30)
71 hcomp[3, j] = max(0.0, hcomp[3, j] + delz)
72 # Question (see the page): He3 (species 4) is not scaled.
73 for i in range(5, 12):
74 hcomp[i, j] = hcomp[i, j] * zfact
75 comp.znew = rescal[3, nk]
76 label_mod.zenv0 = rescal[3, nk]
77 comp.zenv = label_mod.zenv0
78 else:
79 i1 = 3
80 w(ishort, " ERROR IN SUBROUTINE RSCALE") # format 1002
81 w(ishort, f" RESCALING OF Z IN KIND CARD #{nk:3d} FAILED - "
82 f"DESIRED COMP{rescal[i1, nk]:9.6f}")
83 w(ishort, " GREATER THAN UNITY. Z NOT RESCALED")
84
85 # Main sequence: one species set everywhere (Fortran lines 150–180).
86 if hcomp[1, 1] > 1.0e-10:
87 # Question (see the page): one xnewcp for all kind cards.
88 if nml.lnewcp and nml.xnewcp >= 0.0:
89 # A relative target is converted into a local, xtarg.
90 xtarg = nml.xnewcp
91 if nml.lrel:
92 xtarg = math.exp(c.cln * (nml.xnewcp - 12.0)) * hcomp[1, m]
93 if xtarg < 1.0:
94 for i in range(1, m + 1):
95 hcomp[nml.inewcp, i] = xtarg
96 else:
97 # Suspected bug (see the page): ICOMP is never set (0 here).
98 icomp = 0
99 w(ishort, " ERROR IN SUBROUTINE RSCALE") # format 1004
100 w(ishort, f" RESCALING OF SPECIES {icomp:3d} IN KIND CARD # "
101 f"{nk:3d} FAILED - DESIRED COMP{xtarg:9.6f}")
102 w(ishort, " GREATER THAN UNITY. Z NOT RESCALED")
103
104 # The total mass: every mass point scaled (Fortran lines 181–192).
105 if rescal[1, nk] > 0.0:
106 hstot1 = math.log10(rescal[1, nk] / smass)
107 hstot = hstot + hstot1
108 smass = rescal[1, nk]
109 comp.stotal = hstot
110 for i in range(1, m + 1):
111 hs[i] = hs[i] + hstot1
112 else:
113 # Horizontal branch: the old masses (Fortran lines 193–226).
114 if rescal[1, nk] > 0.0 or rescal[4, nk] > 0.0:
115 jcore, jenv, jxbeg, jxend, jxmid, lshell = findsh(
116 hcomp, hl, lc, m, 0, 0, 0, 0, 0, False)
117 corold = math.exp(c.cln * hs[jxbeg - 1]) / c.cmsun
118 envold = (math.exp(c.cln * hstot)
119 - math.exp(c.cln * hs[jxend])) / c.cmsun
120 envold2 = (math.exp(c.cln * hs[m])
121 - math.exp(c.cln * hs[jxend])) / c.cmsun
122 shlold = (math.exp(c.cln * hs[jxend])
123 - math.exp(c.cln * hs[jxbeg - 1])) / c.cmsun
124 denv = 0.0
125 dcor = 0.0
126 w(ishort, f" HB-OLD MASSES: CORE {corold:9.6f} SHELL "
127 f"{shlold:9.6f} ENV {envold:9.6f} TOTAL{smass:9.6f}")
128
129 # The total mass: the mass coordinate stretched above m_0 (Fortran lines 228–237).
130 if rescal[1, nk] > 0.0:
131 denv = rescal[1, nk] - smass
132 envnew = envold + denv
133 # Question (see the page): the 0.01 Msun switch.
134 if ((10.0 ** hstot) / c.cmsun) - corold >= 0.01:
135 # The old method: m_0 at the top of the shell (Fortran lines 240–283).
136 # Question (see the page): debug output.
137 print(" Entering old method ",
138 (10.0 ** hstot - 10.0 ** hs[m])
139 / (10.0 ** hs[m] - 10.0 ** hs[jxbeg - 1]))
140 print(" SENV ", 10.0 ** hstot - 10.0 ** hs[m])
141 print(" Envelope ", 10.0 ** hs[m] - 10.0 ** hs[jxbeg - 1])
142 if envnew <= 0.0:
143 _error_stop([ # format 69
144 " ERROR IN SUBROUTINE RSCALE",
145 " DESIRED NEW ENVELOPE MASS LESS THAN ZERO",
146 f" OLD ENVELOPE MASS {envold:9.2E} NEW ENVELOPE "
147 f"{envold + denv:9.2E} NEW AND OLD TOTAL MASS "
148 f"{rescal[1, nk]:10.2E}{smass:10.2E}"])
149
150 # The scale factor and the new masses (Fortran lines 260–276).
151 hse = hs[jxend]
152 sfactor = ((rescal[1, nk] - math.exp(c.cln * hse) / c.cmsun)
153 / (smass - math.exp(c.cln * hse) / c.cmsun))
154 hstot = math.log10(10.0 ** hse
155 + sfactor * (10.0 ** hstot - 10.0 ** hse))
156 smass = rescal[1, nk]
157 comp.stotal = hstot
158 for i in range(jxend + 1, m + 1):
159 hs[i] = math.log10(10.0 ** hs[jxend]
160 + sfactor * (10.0 ** hs[i]
161 - 10.0 ** hs[jxend]))
162 envold = envnew
163 else:
164 # The new method: m_0 at the base of the shell (Fortran lines 285–331).
165 # Question (see the page): debug output.
166 print(" Entering new method ",
167 (10.0 ** hstot - 10.0 ** hs[m])
168 / (10.0 ** hs[m] - 10.0 ** hs[jxbeg - 1]))
169 print(" SENV ", 10.0 ** hstot - 10.0 ** hs[m])
170 print(" Envelope ", 10.0 ** hs[m] - 10.0 ** hs[jxbeg - 1])
171
172 # Suspected bug (see the page): the new total mass is not checked
173 # against the core.
174 chkenv = ((10.0 ** hstot) / c.cmsun) - corold
175 if chkenv <= 0.0:
176 _error_stop([ # format 69
177 " ERROR IN SUBROUTINE RSCALE",
178 " DESIRED NEW ENVELOPE MASS LESS THAN ZERO",
179 f" OLD ENVELOPE MASS {envold:9.2E} NEW ENVELOPE "
180 f"{envold + denv:9.2E} NEW AND OLD TOTAL MASS "
181 f"{rescal[1, nk]:10.2E}{smass:10.2E}"])
182
183 # The scale factor and the new masses (Fortran lines 307–324).
184 hsb = hs[jxbeg - 1]
185 sfactor = ((rescal[1, nk] - math.exp(c.cln * hsb) / c.cmsun)
186 / (smass - math.exp(c.cln * hsb) / c.cmsun))
187 hstot = math.log10(10.0 ** hsb
188 + sfactor * (10.0 ** hstot - 10.0 ** hsb))
189 smass = rescal[1, nk]
190 comp.stotal = hstot
191 # HS(JXBEG-1) itself is not in the loop, so hsb stays valid.
192 for i in range(jxbeg, m + 1):
193 hs[i] = math.log10(10.0 ** hsb + sfactor
194 * (10.0 ** hs[i] - 10.0 ** hsb))
195 envold = (math.exp(c.cln * hstot)
196 - math.exp(c.cln * hs[jxend])) / c.cmsun
197 envtotal = (math.exp(c.cln * hs[m]) # noqa: F841 (unused in the Fortran too)
198 - math.exp(c.cln * hs[jxbeg - 1])) / c.cmsun
199
200 # The core mass: core scaled, shell shifted, envelope squeezed (Fortran lines 337–380).
201 if rescal[4, nk] > 0.0:
202 shlp = math.exp(c.cln * hs[jxend])
203 dcor = rescal[4, nk] - corold
204 denv = -dcor
205 envnew = envold2 + denv
206 if envnew <= 0.0:
207 _error_stop([ # format 71
208 " ERROR IN SUBROUTINE RSCALE",
209 " NEW ENVELOPE MASS LESS THAN ZERO BECAUSE OF CORE "
210 "RESCALING",
211 f" OLD ENVELOPE MASS {envold:10.2E} NEW ENVELOPE "
212 f"{envnew:10.2E} NEW AND OLD CORE MASS "
213 f"{rescal[4, nk]:10.2E}{corold:10.2E}"])
214 hstot1 = math.log10(rescal[4, nk] / corold)
215 for i in range(1, jxbeg):
216 hs[i] = hs[i] + hstot1
217 shift = dcor * c.cmsun
218 for i in range(jxbeg, jxend + 1):
219 temp = math.exp(c.cln * hs[i])
220 hs[i] = math.log10(temp + shift)
221 sfactor = ((math.exp(c.cln * hs[m])
222 - math.exp(c.cln * hs[jxend]))
223 / (math.exp(c.cln * hs[m]) - shlp))
224 for i in range(jxend + 1, m + 1):
225 hs[i] = math.log10(10.0 ** hs[m]
226 - sfactor * (10.0 ** hs[m] - 10.0 ** hs[i]))
227
228 # The new masses printed (Fortran lines 382–390).
229 if rescal[1, nk] > 0.0 or rescal[4, nk] > 0.0:
230 cornew = math.exp(c.cln * hs[jxbeg - 1]) / c.cmsun
231 envnew = (math.exp(c.cln * hstot)
232 - math.exp(c.cln * hs[jxend])) / c.cmsun
233 shlnew = (math.exp(c.cln * hs[jxend])
234 - math.exp(c.cln * hs[jxbeg - 1])) / c.cmsun
235 w(ishort, f" HB-RESCALED MASSES: CORE {cornew:9.6f} SHELL "
236 f"{shlnew:9.6f} ENV {envnew:9.6f} TOTAL {smass:9.6f}")
237
238 # Y = 1 - X - Z - X(He3) everywhere (Fortran lines 392–395).
239 for i in range(1, m + 1):
240 hcomp[2, i] = 1.0 - hcomp[1, i] - hcomp[3, i] - hcomp[4, i]
241
242 # ZRAMP: Z = Z_c inside RSCLZM1, rising linearly to the surface Z at
243 # RSCLZM2 (in fractions of the total mass) (Fortran lines 397–426).
244 if (nml.lzramp and nml.rsclzc[nk] > 0.0 and nml.rsclzm1[nk] > 0.0
245 and nml.rsclzm2[nk] > 0.0):
246 slope = (comp.znew - nml.rsclzc[nk]) / (nml.rsclzm2[nk]
247 - nml.rsclzm1[nk])
248 for i in range(1, m + 1):
249 fs = 10.0 ** hs[i] / (smass * c.cmsun)
250 if fs < nml.rsclzm1[nk]:
251 zp = nml.rsclzc[nk]
252 elif fs < nml.rsclzm2[nk]:
253 zp = (fs - nml.rsclzm1[nk]) * slope + nml.rsclzc[nk]
254 else:
255 continue
256 zfact = zp / (hcomp[3, i] + 1.0e-30)
257 hcomp[3, i] = zp
258 hcomp[1, i] = 1.0 - hcomp[3, i] - hcomp[4, i] - hcomp[2, i]
259 for j in range(5, 12):
260 hcomp[j, i] = hcomp[j, i] * zfact
261
262 return hstot, smass