VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
fouri.f90
Go to the documentation of this file.
1
3
13SUBROUTINE fouri(grpmn, gsource, amatrix, amatsq, bvec, wint, lasym)
14 USE vacmod, vm_amatrix => amatrix, vm_grpmn => grpmn
15
16 use dbgout
18
19 IMPLICIT NONE
20
21 REAL(rprec), DIMENSION(mnpd,nv,nu3,ndim), INTENT(in) :: grpmn
22 REAL(rprec), DIMENSION(nuv), INTENT(in) :: gsource
23 REAL(rprec), DIMENSION(mnpd,mnpd,ndim**2), INTENT(out) :: amatrix
24 REAL(rprec), DIMENSION(mnpd2,mnpd2), INTENT(out) :: amatsq
25 REAL(rprec), DIMENSION(0:mf,-nf:nf,ndim), INTENT(inout) :: bvec
26 REAL(rprec), DIMENSION(nuv2), intent(in) :: wint
27 logical, intent(in) :: lasym
28
30 REAL(rprec), PARAMETER :: int_ext = 1
31
32 INTEGER :: k, i, j, n, kvi, kui, mn, m, mn0, isym
33 REAL(rprec) :: cosn, sinn, cosm, sinm
34
35 ! AMATRIX(,1) = A(Sin)(Sin'); AMATRIX(,2) = A(Sin)(Cos');
36 ! AMATRIX(,3) = A(Cos)(Sin'); AMATRIX(,4) = A(Cos)(Cos')
37 !
38 ! ARG OF TRIG FUNCTIONS: m'u' - n'v' CORRESPONDING TO THE PRIMED MESH IN
39 ! PKM EQ.(2.14), AND mu - nv (UNPRIMED MESH) IN EQ. (2.16)
40 !
41 ! ON ENTRY, GRPMN(MN,...) HAS BEEN FOURIER-TRANSFORMED OVER THE UNPRIMED
42 ! COORDINATES (IN FOURP), SO THE FIRST INDEX OF GRPMN CORRESPONDS TO THE FIRST
43 ! INDEX OF AMATRIX. THUS, THE FOURIER TRANSFORMS OF GRPMN HERE ARE OVER THE PRIMED MESH.
44 !
45 ! IN CONTRAST, THE INTEGRAL OF THE SOURCE TERM OVER THE PRIMED MESH WAS ALREADY
46 ! DONE (IN SCALPOT), SO HERE THE FT ARE OVER THE UNPRIMED MESH FOR THE SOURCE.
47
48 ! SYMMETRIZE SOURCE TERMS (with respect to u,v and -u,-v)
49 ! INDEX (1) IS ANTI-SYMMETRIC, INDEX (2) IS SYMMETRIC, PART
50 !
51 ! GSOURCE = - (2pi)**2 B * dS (h - hsing) * WINT
52 !
53 ! WINT: needed to normalize integral over angles to unity
54 k = 0
55 DO i = 1, nu2
56 DO j = 1, nv
57 k = k + 1
58
59 ! anti-symmetric part
60 source(j,i,1) = gsource(k) - gsource(imirr(k))
61
62 ! gsource_sym.dat
63 ! print *, i, j, source(j,i,1)
64
65 IF (lasym) then
66 ! symmetric part
67 source(j,i,2) = gsource(k) + gsource(imirr(k))
68 end if
69 END DO
70 END DO
71
72 ! 0.5 from above symmetrization
73 ! 1/nfp to match 1/nfp in alp in cmns (2 pi of alp alreafy somewhere else (???))
74 source = p5*onp*source ! TODO: why is this required?
75
76 ! INITIALIZE RUNNING-SUM ARRAYS
77 bcos = 0
78 bsin = 0
79 actemp = 0
80 astemp = 0
81
82 ! PERFORM KV (TOROIDAL ANGLE) TRANSFORM
83 DO n = 0, nf
84 DO kvi = 1, nv
85 cosn = cosv(n,kvi)
86 sinn = sinv(n,kvi)
87 DO isym = 1, ndim
88 bcos(:,n,isym) = bcos(:,n,isym) + cosn*source(kvi,:,isym)
89 bsin(:,n,isym) = bsin(:,n,isym) + sinn*source(kvi,:,isym)
90
91 ! first index: mnpd == (mf + 1) * (2 * nf + 1)
92 ! second index: 2 * nf + 1
93 ! third index: nu3
94 actemp(:,n,:,isym) = actemp(:,n,:,isym) + cosn*grpmn(:,kvi,:,isym)
95 astemp(:,n,:,isym) = astemp(:,n,:,isym) + sinn*grpmn(:,kvi,:,isym)
96
97 IF (n .ne. 0) THEN
98 bcos(:,(-n),isym) = bcos(:,n,isym)
99 bsin(:,(-n),isym) = -bsin(:,n,isym)
100
101 actemp(:,(-n),:,isym) = actemp(:,n,:,isym)
102 astemp(:,(-n),:,isym) = -astemp(:,n,:,isym)
103 ENDIF
104 END DO ! isym
105 END DO ! kvi
106 END DO ! n
107
108
109
110 amatrix = 0
111
112 ! PERFORM KU (POLOIDAL ANGLE) TRANSFORM
113 DO m = 0, mf
114 DO kui = 1, nu2
115 cosm = cosui(m,kui) ! includes (2 pi)^2 via alu, alv
116 sinm = sinui(m,kui) ! includes (2 pi)^2 via alu, alv
117 bvec(m,-nf:nf,1) = bvec(m,-nf:nf,1) + bcos(kui,-nf:nf,1)*sinm - bsin(kui,-nf:nf,1)*cosm
118 IF (lasym) THEN
119 bvec(m,-nf:nf,2) = bvec(m,-nf:nf,2) + bcos(kui,-nf:nf,2)*cosm + bsin(kui,-nf:nf,2)*sinm
120 END IF
121 END DO
122
123 ! RECALL, LAST INDEX OF A(S,C)TEMP
124 ! = 1 CORRESPONDS TO SIN (UNPRIMED) TRANSFORM (FIRST INDEX OF AMATRIX)
125 ! = 2 CORRESPONDS TO COS (UNPRIMED) TRANSFORM
126 DO kui = 1, nu3
127 cosm = cosu(m,kui)*wint(kui*nv) ! wint only varies in the poloidal direction --> only need every nv-th entry
128 sinm = sinu(m,kui)*wint(kui*nv)
129
130 ! SIN SIN'
131 amatrix(:,m+1:mnpd:mf1,1) = amatrix(:,m+1:mnpd:mf1,1) + sinm*actemp(:,-nf:nf,kui,1) - cosm*astemp(:,-nf:nf,kui,1)
132
133 IF (lasym) then
134 ! SIN COS'
135 amatrix(:,m+1:mnpd:mf1,2) = amatrix(:,m+1:mnpd:mf1,2) + cosm*actemp(:,-nf:nf,kui,1) + sinm*astemp(:,-nf:nf,kui,1)
136
137 ! COS SIN'
138 amatrix(:,m+1:mnpd:mf1,3) = amatrix(:,m+1:mnpd:mf1,3) + sinm*actemp(:,-nf:nf,kui,2) - cosm*astemp(:,-nf:nf,kui,2)
139
140 ! COS COS'
141 amatrix(:,m+1:mnpd:mf1,4) = amatrix(:,m+1:mnpd:mf1,4) + cosm*actemp(:,-nf:nf,kui,2) + sinm*astemp(:,-nf:nf,kui,2)
142 end if
143
144 END DO
145 END DO
146
147
148 ! debugging: first focus on above Fourier transforms
149 ! return
150
151
152 ! The code below is not related to Fourier transforms anymore,
153 ! so it should probably go into the main vacuum routine...
154
155 amatrix = (pi2*pi2)*amatrix ! TODO: can this be cancelled with some factors of 2*pi in the rest of NESTOR?
156
157 ! ZERO BVEC(0,n) FOR n < 0 (TODO: why ?)
158 ! Fixed SPH081515: had -nf:0 before
159 bvec(0,-nf:-1,1:ndim) = 0
160
161 ! ZERO AMATRIX(0,n,m',n') M = 0 MODES FOR n < 0 (TODO: why ?)
162 ! Index of m=0,n=0
163 mn0 = 1+mf1*nf
164 ! SPH082415: mn0-mf1: (m=0,n=-1 index)
165 amatrix(1:mn0-mf1:mf1, :, 1:ndim*ndim) = 0
166
167 ! ADD DIAGONAL TERMS TO AMATRIX [THE FIRST TERM IN EQ(3.2) OF PKM]
168 DO mn = 1, mnpd
169 amatrix(mn,mn,1) = amatrix(mn,mn,1) + pi3*int_ext
170 END DO
171
172 IF (lasym) THEN
173 DO mn = 1, mnpd
174 ! last index == 4 is the lower-right corner of amatrix
175 ! and this corner is crossed by the main diagnoal as well
176 ! --> no need to touch 2 and 3 (off-diagonal blocks of amatrix)
177 amatrix(mn,mn,4) = amatrix(mn,mn,4) + pi3*int_ext
178 END DO
179
180 ! COS(0-0) mode *2 (TODO: why is this required ?)
181 ! maybe has to do with mscale and nscale
182 ! --> orthogonality of Fourier basis for cos ?
183 amatrix(mn0,mn0,4) = amatrix(mn0,mn0,4) + pi3*int_ext
184 END IF
185
186 ! PUT ELEMENTS INTO SQUARE MATRIX
187
188 ! Sin-Sin'
189 amatsq(:mnpd,:mnpd) = amatrix(:,:,1)
190
191 IF (lasym) then
192 ! Sin-Cos'
193 amatsq(:mnpd,1+mnpd:mnpd2) = amatrix(:,:,2)
194
195 ! Cos-Sin'
196 amatsq(1+mnpd:mnpd2,:mnpd) = amatrix(:,:,3)
197
198 ! Cos-Cos'
199 amatsq(1+mnpd:mnpd2,1+mnpd:mnpd2) = amatrix(:,:,4)
200 end if
201
202 if (open_dbg_context("vac1n_fouri", num_eqsolve_retries)) then
203
204 ! TODO: isym for lasym=.TRUE.
205 call add_real_2d("source", nv, nu2, source)
206
207 call add_real_2d("bcos", nu2, nf1, bcos)
208 call add_real_2d("bsin", nu2, nf1, bsin)
209
210 call add_real_4d("actemp", mf1, nf1, nf1, nu3, actemp)
211 call add_real_4d("astemp", mf1, nf1, nf1, nu3, astemp)
212
213 call add_real_2d("bvec", mf1, nf1, bvec)
214 call add_real_4d("amatrix", mf1, nf1, mf1, nf1, amatrix)
215
216 call add_real_2d("amatsq", mf1*nf1, mf1*nf1, amatsq)
217
218 call close_dbg_out()
219 end if
220
221END SUBROUTINE fouri
subroutine fouri(grpmn, gsource, amatrix, amatsq, bvec, wint, lasym)
Compute Fourier integrals and build amatrix.
Definition fouri.f90:14
logical function open_dbg_context(context_name, repetition, id)
check if any output is desired for the current iteration check if the given context should be openend...
Definition dbgout.f90:17
real(rprec), dimension(:,:,:,:), allocatable actemp
Definition vacmod.f90:159
real(rprec), dimension(:), allocatable grpmn
Definition vacmod.f90:102
real(rprec), dimension(:,:,:), allocatable source
Definition vacmod.f90:157
real(rprec), dimension(:,:,:), allocatable bcos
Definition vacmod.f90:155
real(rprec) pi3
Definition vacmod.f90:18
real(rprec), dimension(:,:,:,:), allocatable astemp
Definition vacmod.f90:160
real(rprec), parameter p5
Definition vacmod.f90:13
real(rprec) pi2
Definition vacmod.f90:17
real(rprec), dimension(:,:,:), allocatable bsin
Definition vacmod.f90:156
real(rprec), dimension(:), allocatable amatrix
Definition vacmod.f90:83
real(rprec) onp
Definition vacmod.f90:24
integer num_eqsolve_retries