1C $$$$$$
2 SUBROUTINE EQ2MOD(DJ,EJ,HS2,IBEG,IEND,LCZ,M,SUMDJ,HJM)
3C 10/15/26 MHP via Claude
4C code changed to take JSON from DIMENSIONS_MOD instead of declaring
5C PARAMETER(JSON=5000) here.
6 USE DIMENSIONS_MOD
7C 10/14/26 MHP via Claude
8C code changed to convert COMMON/SPLIN/ into SPLIN_MOD.
9 USE SPLIN_MOD
10C 10/14/26 MHP via Claude
11C code changed to convert COMMON/EGRID/ into EGRID_MOD.
12 USE EGRID_MOD
13C 10/20/26 MHP via Claude
14C code changed to replace implicit typing with IMPLICIT NONE and
15C explicit declarations.
16 IMPLICIT NONE
17 REAL*8 DJ,EJ,HJM,HS2,RATIO,SUMDJ,SUMDJMOD,SUMJMOD,TEST,VAL
18 INTEGER I,I0,I1,IBEG,IEND,II,M,NMOD
19 LOGICAL*4 LCZ
20 DIMENSION DJ(JSON),EJ(JSON),HS2(JSON),LCZ(JSON),HJM(JSON)
21 SAVE
22C THE DIFFUSION EQUATION FOR ANGULAR MOMENTUM TRANSPORT IS SOLVED USING AN
23C EQUALLY SPACED GRID FOR EACH UNSTABLE REGION. ONCE THE EQUATION HAS
24C BEEN SOLVED, WE NEED THE NEW RUN OF ANGULAR MOMENTUM AT THE ORIGINAL
25C MODEL POINTS.
26C
27C EQUAL2 TRANSFORM BACK TO THE ORIGINAL GRID AND CALCULATE THE CHANGE IN
28C SPECIFIC ANGULAR MOMENTUM IN EACH SHELL.
29C
30C INPUT VARIABLES:
31C
32C VARIABLES PERTAINING TO THE EQUALLY SPACED GRID POINTS USED TO SOLVE
33C THE DIFFUSION EQUATION :
34C
35C DJ - CHANGE IN J AT EACH POINT DUE TO ROTATIONALLY INDUCED INSTABILITIES.
36C EJ - CONTAINS THE RUN OF ANGULAR MOMENTUM PRIOR TO ANGULAR MOMENTUM
37C REDISTRIBUTION.
38C NTOT - NUMBER OF EQUALLY SPACED GRID POINTS IN THE UNSTABLE REGION.
39C SUMDJ - TOTAL CHANGE IN ANGULAR MOMENTUM ACROSS GRID
40C VARIABLES PERTAINING TO THE ORIGINAL MODEL POINTS :
41C
42C HS2 - THE UNLOGGED MASS CONTENT OF THE MODEL POINTS.
43C IBEG,IEND - THE FIRST AND LAST MODEL POINTS CONTAINED IN THE UNSTABLE
44C REGION.
45C LCZ - A LOGICAL ARRAY WHICH IS T IF THE MODEL POINT IS CONVECTIVE FOR
46C ANGULAR MOMENTUM PURPOSES AND F OTHERWISE.
47C M - THE TOTAL NUMBER OF MODEL POINTS.
48C
49C VARIABLES IN COMMON BLOCKS:
50C
51C /SPLIN/ CONTAINS DUMMY ARRAYS USED TO PERFORM AN OSCULATORY SPLINE
52C INTERPOLATION.
53C /EGRID/ CONTAINS THE VECTOR OF EQUALLY SPACED GRID POINTS.
54C OUTPUT VARIABLE :
55C HJM - THE NEW RUN OF SPECIFIC ANGULAR MOMENTUM AT THE MODEL POINTS.
56C -------------------------------------------------------------------------
57C CHECK FOR LOWER AND UPPER CONVECTION ZONES.
58C 10/30/26 MHP via Claude
59C code changed to widen the write-back with the test ROTGRID's sums use:
60C any convection zone adjoining the region, whether or not the end zone
61C is itself convective. The sums took that zone into the end cell, but
62C its change went to the end zone alone when that zone was radiative.
63 IF(IBEG.EQ.1)THEN
64 I0 = IBEG
65 ELSE
66 DO I = IBEG - 1, 1, -1
67 IF(.NOT.LCZ(I))THEN
68 I0 = I + 1
69 GOTO 10
70 ENDIF
71 END DO
72 I0 = 1
73 10 10 CONTINUE
74 ENDIF
75 IF(IEND.EQ.M)THEN
76 I1 = IEND
77 ELSE
78 DO I = IEND+1,M
79 IF(.NOT.LCZ(I))THEN
80 I1 = I - 1
81 GOTO 20
82 ENDIF
83 END DO
84 I1 = M
85 20 20 CONTINUE
86 ENDIF
87C INTERPOLATE IN DJ/J AS A FUNCTION OF ECHI
88 NMOD = IEND - IBEG + 1
89 DO I = 1, NMOD
90 XVAL(I) = CHI(I)
91 END DO
92 DO I = 1,NTOT
93 XTAB(I) = ECHI(I)
94 YTAB(I) = DJ(I)/EJ(I)
95 END DO
96 CALL OSPLIN(XVAL,YVAL,XTAB,YTAB,NTOT,NMOD)
97C APPLY THE FRACTIONAL CHANGE IN J/M ACROSS THE MODEL.
98 SUMJMOD = 0.0D0
99 SUMDJMOD = 0.0D0
100 IF(I0.LT.IBEG)THEN
101 DO I = I0,IBEG-1
102 SUMJMOD = SUMJMOD + HJM(I)*HS2(I)
103 SUMDJMOD = SUMDJMOD + YVAL(1)*HJM(I)*HS2(I)
104 HJM(I) = HJM(I)*(1.0D0+YVAL(1))
105 END DO
106 ENDIF
107 DO I = IBEG,IEND
108 II = I - IBEG + 1
109 SUMJMOD = SUMJMOD + HJM(I)*HS2(I)
110 SUMDJMOD = SUMDJMOD + YVAL(II)*HJM(I)*HS2(I)
111 HJM(I) = HJM(I)*(1.0D0+YVAL(II))
112 END DO
113 IF(I1.GT.IEND)THEN
114 DO I = IEND+1,I1
115 SUMJMOD = SUMJMOD + HJM(I)*HS2(I)
116 SUMDJMOD = SUMDJMOD + YVAL(NMOD)*HJM(I)*HS2(I)
117 HJM(I) = HJM(I)*(1.0D0+YVAL(NMOD))
118 END DO
119 ENDIF
120C CHECK THAT ANGULAR MOMENTUM HAS BEEN CONSERVED. THE TOTAL ANGULAR
121C MOMENTUM CAN BE REDUCED FROM SURFACE ANGULAR MOMENTUM LOSS; CARE IS
122C USED HERE BECAUSE DUMDJ SHOULD BE ZERO IN MODELS WITHOUT LOSS.
123 TEST = ABS(SUMDJMOD - SUMDJ)
124 VAL = 1.0D-5*ABS(SUMDJ)
125c WRITE(*,*)SUMDJ,SUMDJMOD,SUMJMOD
126c WRITE(*,911)(DJ(I)/EJ(I),I=1,NTOT)
127C 911 FORMAT(1P8E10.2)
128C IF THE TEST SUM IS NOT THE SAME WITHIN THE RELATIVE TOLERANCE VAL,
129C ADJUST THE TOTAL ANGULAR MOMENTUM OF THE ENTIRE REGION BY A CONSTANT
130C FACTOR TO ENFORCE ANGULAR MOMENTUM CONSERVATION.
131 IF(TEST.GT.VAL)THEN
132 RATIO = (SUMJMOD + SUMDJ)/(SUMJMOD + SUMDJMOD)
133 DO I = I0, I1
134 HJM(I) = HJM(I)*RATIO
135 END DO
136 ENDIF
137 RETURN
138 END
1"""Python version of eq2mod.f (YREC 7be4133): a change of specific angular
2momentum on the even grid, mapped back onto the model's points."""
3
4import numpy as np
5
6from pyrec import egrid_mod
7from pyrec import splin_mod
8from pyrec.osplin import osplin
9
10
11def eq2mod(dj: np.ndarray, ej: np.ndarray, hs2: np.ndarray, ibeg: int, iend: int, lcz: np.ndarray, m: int, sumdj: float,
12 hjm: np.ndarray) -> None:
13 """Interpolate Delta j / j from the even grid back to the model points
14 of the region ibeg..iend (extended to the edges of convection zones it
15 touches), apply it to hjm, and rescale the region so that its angular
16 momentum changes by exactly sumdj.
17
18 Translates: eq2mod.f#EQ2MOD (7be4133)
19
20 Arguments: dj, ej, the change and the angular momentum on the even
21 grid; hs2, the shell masses; ibeg, iend, the region; lcz, the
22 convective flags; m, the number of shells; sumdj, the total change;
23 hjm, the specific angular momentum, changed in place.
24
25 Returns nothing.
26
27 """
28
29 chi = egrid_mod.chi
30 echi = egrid_mod.echi
31 ntot = egrid_mod.ntot
32 xval = splin_mod.xval
33 yval = splin_mod.yval
34 xtab = splin_mod.xtab
35 ytab = splin_mod.ytab
36
37 # Extend the region over the convection zones adjoining its ends
38 # (Fortran lines 57–86).
39 if ibeg == 1:
40 i0 = ibeg
41 else:
42 i0 = 1
43 for i in range(ibeg - 1, 0, -1):
44 if not lcz[i]:
45 i0 = i + 1
46 break # label 10
47
48 if iend == m:
49 i1 = iend
50 else:
51 i1 = m
52 for i in range(iend + 1, m + 1):
53 if not lcz[i]:
54 i1 = i - 1
55 break # label 20
56
57 # Interpolate y = dj/ej from the even grid to the model points
58 # (Fortran lines 87–96).
59 nmod = iend - ibeg + 1
60 for i in range(1, nmod + 1):
61 xval[i] = chi[i]
62 for i in range(1, ntot + 1):
63 xtab[i] = echi[i]
64 ytab[i] = dj[i] / ej[i]
65 osplin(xval, yval, xtab, ytab, ntot, nmod)
66
67 # Apply it; the extended convective shells take the edge values.
68 # Question (see the page): this assumes those zones rotate as solid
69 # bodies already (Fortran lines 97–119).
70 sumjmod = 0.0
71 sumdjmod = 0.0
72 if i0 < ibeg:
73 for i in range(i0, ibeg):
74 sumjmod = sumjmod + hjm[i] * hs2[i]
75 sumdjmod = sumdjmod + yval[1] * hjm[i] * hs2[i]
76 hjm[i] = hjm[i] * (1.0 + yval[1])
77 for i in range(ibeg, iend + 1):
78 ii = i - ibeg + 1
79 sumjmod = sumjmod + hjm[i] * hs2[i]
80 sumdjmod = sumdjmod + yval[ii] * hjm[i] * hs2[i]
81 hjm[i] = hjm[i] * (1.0 + yval[ii])
82 if i1 > iend:
83 for i in range(iend + 1, i1 + 1):
84 sumjmod = sumjmod + hjm[i] * hs2[i]
85 sumdjmod = sumdjmod + yval[nmod] * hjm[i] * hs2[i]
86 hjm[i] = hjm[i] * (1.0 + yval[nmod])
87
88 # Rescale to conserve angular momentum (Fortran lines 120–136).
89 test = abs(sumdjmod - sumdj)
90 val = 1.0e-5 * abs(sumdj)
91 if test > val:
92 ratio = (sumjmod + sumdj) / (sumjmod + sumdjmod)
93 for i in range(i0, i1 + 1):
94 hjm[i] = hjm[i] * ratio