V3FIT
precal.f
1  SUBROUTINE precal (wint)
2  USE vparams, ONLY: zero, one, epstan
3  USE vacmod
4  USE vmec_main, ONLY: mnmax
5  USE parallel_include_module
6  IMPLICIT NONE
7 C-----------------------------------------------
8 C D u m m y A r g u m e n t s
9 C-----------------------------------------------
10  REAL(dp), INTENT(in) :: wint(nuv3)
11 C-----------------------------------------------
12 C L o c a l P a r a m e t e r s
13 C-----------------------------------------------
14  REAL(dp), PARAMETER :: p25 = p5*p5, bigno = 1.e50_dp
15 C-----------------------------------------------
16 C L o c a l V a r i a b l e s
17 C-----------------------------------------------
18  INTEGER :: kp, ku, kuminus, kv, kvminus, i, m, n, mn, n1,
19  1 imn, jmn, kmn, l, istat1, smn, nuv_tan, ndim, q, qq
20  REAL(dp), DIMENSION(0:mf + nf,0:mf,0:nf) :: cmn
21  REAL(dp) :: argu, argv, argp, dn1, f1, f2, f3, alp_per,
22  1 tprecon, tprecoff
23 C-----------------------------------------------
24 !
25 ! THIS ROUTINE COMPUTES INITIAL CONSTANTS AND ARRAYS
26 ! NOTE: alu*alv = (2*pi)**2 * wint
27 !
28  CALL second0(tprecon)
29 
30  pi2 = 8*atan(one)
31  pi3 = p5*pi2**3
32  pi4 = 2*pi2
33  onp = one/nfper
34  onp2 = onp*onp
35  alu = pi2/nu
36  alv = pi2/nv
37  alp = pi2*onp
38  alvp = onp*alv
39 
40 !
41 ! ALLOCATE PERSISTENT ARRAYS. DEALLOCATED IN FILEOUT ROUTINE
42 !
43  IF (nv == 1) THEN !(AXISYMMETRIC CASE: DO FP SUM TO INTEGRATE IN V)
44  nvper = 64
45  nuv_tan = 2*nu*nvper
46  ELSE
47  nvper = nfper
48  nuv_tan = 2*nuv
49  END IF
50 
51  alp_per = pi2/nvper
52  nvp = nv*nvper
53 
54  ALLOCATE (tanu(nuv_tan), tanv(nuv_tan),
55  1 sinper(nvper), cosper(nvper), sinuv(nuv), cosuv(nuv),
56  2 sinu(0:mf,nu), cosu(0:mf,nu), sinv(-nf:nf,nv),
57  3 cosv(-nf:nf,nv), sinui(0:mf,nu2), cosui(0:mf,nu2),
58  4 cmns(0:(mf+nf),0:mf,0:nf), csign(-nf:nf),
59  5 sinu1(nuv3,0:mf), cosu1(nuv3,0:mf),
60  6 sinv1(nuv3,0:nf), cosv1(nuv3,0:nf), imirr(nuv),
61  7 xmpot(mnpd), xnpot(mnpd), stat=istat1)
62  IF (istat1.ne.0) stop 'allocation error in precal'
63 
64 
65 !
66 ! IMIRR(I) GIVES THE INDEX OF THE POINT TWOPI-THETA(I),TWOPI-ZETA(I)
67 !
68  DO kp = 1, nvper
69  cosper(kp) = cos(alp_per*(kp - 1))
70  sinper(kp) = sin(alp_per*(kp - 1))
71  END DO
72 
73  DO ku = 1, nu
74  kuminus = mod(nu + 1 - ku,nu) + 1
75  DO kv = 1, nv
76  kvminus = mod(nv + 1 - kv,nv) + 1
77  i = kv + nv*(ku - 1)
78  imirr(i) = kvminus + nv*(kuminus - 1)
79  cosuv(i) = cos(alvp*(kv - 1))
80  sinuv(i) = sin(alvp*(kv - 1))
81  END DO
82  END DO
83 
84 !
85 ! NOTE: ANGLE DIFFERENCE IS PI2*{[NUV + (KUP-1)] - (KU-1)}
86 ! THIS DIFFERENCE IS ACCOUNTED FOR BY THE OFFSET IUOFF IN GREENF ROUTINE
87 !
88 ! THE KP SUM BELOW IS USED ONLY FOR NV == 1. IT PERFORMS THE V-INTEGRAL
89 ! IN AN AXISYMMETRIC PLASMA
90 !
91  i = 0
92  DO kp = 1, nvper
93  IF (kp.gt.1 .and. nv.ne.1) EXIT
94  argp = p5*alp_per*(kp-1)
95  DO ku = 1, 2*nu
96  argu = p5*alu*(ku - 1)
97  DO kv = 1, nv
98  i = i + 1
99  argv = p5*alv*(kv - 1) + argp
100  IF (abs(argu - p25*pi2)<epstan .or.
101  1 abs(argu - 0.75_dp*pi2) < epstan) THEN
102  tanu(i) = bigno
103  ELSE
104  tanu(i) = 2*tan(argu)
105  ENDIF
106  IF (abs(argv - p25*pi2) < epstan) THEN
107  tanv(i) = bigno
108  ELSE
109  tanv(i) = 2*tan(argv)
110  ENDIF
111  END DO
112  END DO
113  END DO
114 
115  DO m = 0, mf
116  l40: DO ku = 1, nu
117  cosu(m,ku) = cos(alu*(m*(ku - 1)))
118  sinu(m,ku) = sin(alu*(m*(ku - 1)))
119  DO kv = 1, nv
120  i = kv + nv*(ku - 1)
121  IF (i > nuv3) cycle l40
122  cosu1(i,m) = cosu(m,ku)
123  sinu1(i,m) = sinu(m,ku)
124  END DO
125  END DO l40
126  DO ku = 1, nu2
127  cosui(m,ku) = cosu(m,ku)*alu*alv*2
128  sinui(m,ku) = sinu(m,ku)*alu*alv*2
129  IF (ku.eq.1 .or. ku.eq.nu2) cosui(m,ku) = p5*cosui(m,ku)
130  END DO
131  END DO
132 
133  DO n = -nf, nf
134  dn1 = alvp*(n*nfper)
135  csign(n) = sign(one,dn1)
136  l50: DO ku = 1, nu
137  DO kv = 1, nv
138  i = kv + nv*(ku - 1)
139  cosv(n,kv) = cos(dn1*(kv - 1))
140  sinv(n,kv) = sin(dn1*(kv - 1))
141  IF (i.gt.nuv3 .or. n.lt.0) cycle l50
142  cosv1(i,n) = cosv(n,kv)
143  sinv1(i,n) = sinv(n,kv)
144  END DO
145  END DO l50
146  END DO
147 
148  mn = 0
149  imn = nuv3min-1
150  numjs_vac=nuv3max-nuv3min+1
151 
152  ALLOCATE(sinmni(numjs_vac,mnpd), cosmni(numjs_vac,mnpd),stat=i)
153  IF (i .NE. 0) stop 'Allocation error in scalpot'
154  DO n = -nf, nf
155  n1 = abs(n)
156  DO m = 0, mf
157  mn = mn + 1
158  xmpot(mn) = m
159  xnpot(mn) = n*nfper
160  DO i = nuv3min, nuv3max
161  sinmni(i-imn,mn) = wint(i)*(sinu1(i,m)*cosv1(i,n1)
162  1 - csign(n)*cosu1(i,m)*sinv1(i,n1))*(pi2*pi2)
163  cosmni(i-imn,mn) = wint(i)*(cosu1(i,m)*cosv1(i,n1)
164  1 + csign(n)*sinu1(i,m)*sinv1(i,n1))*(pi2*pi2)
165  END DO
166  END DO
167  END DO
168 !
169 ! COMPUTE CMNS AND THE COEFFICIENTS OF T+- IN EQ (A14 AND A13) IN J.COMP.PHYS PAPER (PKM)
170 ! NOTE: HERE, THE INDEX L IN THE LOOP BELOW IS THE SUBSCRIPT OF T+-. THEREFORE,
171 ! L = 2L' + Kmn (L' = INDEX IN EQ. A14, Kmn = |m-n|), WITH LMIN = K AND LMAX = Jmn == m+n.
172 !
173 ! THE FOLLOWING DEFINITIONS PERTAIN (NOTE: kmn <= L <= jmn):
174 !
175 ! F1 = [(L + jmn)/2]! / [(jmn - L)/2]! == [(jmn + kmn)/2 + L']!/[(jmn - kmn)/2 + L']!
176 !
177 ! F2 = [(L + kmn)/2]! == (L' + kmn)!
178 !
179 ! F3 = [(L - kmn)/2]! == (L')!
180 !
181  DO m = 0, mf
182  DO n = 0, nf
183  jmn = m + n
184  imn = m - n
185  kmn = abs(imn)
186  smn = (jmn + kmn)/2 !!Integer: J+K always even
187  f1 = 1
188  f2 = 1
189  f3 = 1
190  DO i = 1, kmn
191  f1 = f1*(smn + 1 - i)
192  f2 = f2*i
193  END DO
194  cmn(0:mf+nf,m,n) = 0
195  DO l = kmn, jmn, 2
196  cmn(l,m,n) = f1/(f2*f3)*((-1)**((l - imn)/2))
197  f1 = f1*p25*((jmn + l + 2)*(jmn - l))
198  f2 = f2*p5*(l + 2 + kmn)
199  f3 = f3*p5*(l + 2 - kmn)
200  END DO
201  END DO
202  END DO
203 !
204 ! Now combine these into a single coefficient (cmns), Eq. A13).
205 ! NOTE: The ALP=2*pi/nfper factor is needed to normalize integral over field periods
206 !
207  DO m = 1,mf
208  DO n = 1,nf
209  cmns(0:mf+nf,m,n) = p5*alp*(cmn(0:mf+nf,m,n) +
210  1 cmn(0:mf+nf,m-1,n) + cmn(0:mf+nf,m,n-1) +
211  2 cmn(0:mf+nf,m-1,n-1))
212  END DO
213  END DO
214  cmns(0:mf+nf,1:mf,0) = (p5*alp)*(cmn(0:mf+nf,1:mf,0)
215  1 + cmn(0:mf+nf,:mf-1,0))
216  cmns(0:mf+nf,0,1:nf) = (p5*alp)*(cmn(0:mf+nf,0,1:nf)
217  1 + cmn(0:mf+nf,0,:nf-1))
218  cmns(0:mf+nf,0,0) = (p5*alp)*(cmn(0:mf+nf,0,0)
219  1 + cmn(0:mf+nf,0,0))
220 
221  numjs_vac=nuv3max-nuv3min+1
222 ! blksize_scp=mnpd2
223 
224  ALLOCATE (counts_vac(vnranks),disps_vac(vnranks), stat=i)
225  IF (i .NE. 0) stop 'Allocation error in precal'
226  DO i = 1, vnranks
227  counts_vac(i) = nuv3max_arr(i) - nuv3min_arr(i) + 1
228  END DO
229  disps_vac(1)=0
230  DO i = 2, vnranks
231  disps_vac(i) = disps_vac(i - 1) + counts_vac(i - 1)
232  END DO
233 
234  CALL second0(tprecoff)
235  precal_time = precal_time + (tprecoff - tprecon)
236 
237  END SUBROUTINE precal