VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
forces.f90
Go to the documentation of this file.
1
3
6SUBROUTINE forces
7 USE vmec_main, p5 => cp5
8 USE realspace
9
10 ! I guess these double aliases are intended to show at which point in the code
11 ! the respective arrays hold what quantity...
12 ! E.g., ru12 gets filled by jacobian() and is overwritten with the force component azmn_e here.
13 USE vforces, ru12 => azmn_e, zu12 => armn_e, &
14 azmn_e => azmn_e, armn_e => armn_e, &
15 lv_e => crmn_e, lu_e => czmn_e, lu_o => czmn_o, &
17
18 use dbgout
19
20 IMPLICIT NONE
21
22 REAL(rprec), PARAMETER :: p25 = p5*p5
23 REAL(rprec), PARAMETER :: dshalfds=p25
24
25 INTEGER :: l, js, lk, ku
26 INTEGER :: ndim
27 REAL(rprec), DIMENSION(:), POINTER :: bsqr
28 REAL(rprec), DIMENSION(:), POINTER :: gvvs
29 REAL(rprec), DIMENSION(:), POINTER :: guvs
30 REAL(rprec), DIMENSION(:), POINTER :: guus
31
32 logical :: dbg_forces
33
34 character(len=255) :: dump_filename2
35
36 ! ON ENTRY, ARMN=ZU, BRMN=ZS, AZMN=RU, BZMN=RS, LU=R*BSQ, LV = BSQ*SQRT(G)/R12
37 ! HERE, XS (X=Z,R) DO NOT INCLUDE DERIVATIVE OF EXPLICIT SQRT(S)
38 ! BSQ = |B|**2/2 + p
39 ! GIJ = (BsupI * BsupJ) * SQRT(G) (I,J = U,V)
40 ! IT IS ESSENTIAL THAT LU,LV AT j=1 ARE ZERO INITIALLY
41 !
42 ! SOME OF THE BIGGER LOOPS WERE SPLIT TO FACILITATE CACHE HITS, PIPELINING ON RISCS
43 !
44 ! ORIGIN OF VARIOUS TERMS
45 !
46 ! LU : VARIATION OF DOMINANT RADIAL-DERIVATIVE TERMS IN JACOBIAN
47 !
48 ! LV : VARIATION OF R-TERM IN JACOBIAN
49 !
50 ! GVV: VARIATION OF R**2-TERM AND Rv**2,Zv**2 IN gvv
51 !
52 ! GUU, GUV: VARIATION OF Ru, Rv, Zu, Zv IN guu, guv
53
54 ! inputs:
55 ! lu_e, lv_e
56 ! guu, guv, gvv
57 ! ru12, zu12
58 ! brmn_e, bzmn_e
59 ! r1, z1, ru, zu, ru0, zu0
60 ! rcon, zcon, rcon0, zcon0, gcon
61 ! if lthreed:
62 ! rv, zv
63
64 dbg_forces = open_dbg_context("forces", num_eqsolve_retries)
65 if (dbg_forces) then
66
67 call add_real_3d("lu_e", ns, nzeta, ntheta3, lu_e )
68 call add_real_3d("lv_e_in", ns, nzeta, ntheta3, lv_e )
69 call add_real_3d("guu_in", ns, nzeta, ntheta3, guu )
70 call add_real_3d("guv_in", ns, nzeta, ntheta3, guv )
71 call add_real_3d("gvv_in", ns, nzeta, ntheta3, gvv )
72 call add_real_3d("ru12", ns, nzeta, ntheta3, ru12 )
73 call add_real_3d("zu12", ns, nzeta, ntheta3, zu12 )
74 call add_real_3d("brmn_e_in", ns, nzeta, ntheta3, brmn_e )
75 call add_real_3d("bzmn_e_in", ns, nzeta, ntheta3, bzmn_e )
76 call add_real_3d("ru0", ns, nzeta, ntheta3, ru0 )
77 call add_real_3d("zu0", ns, nzeta, ntheta3, zu0 )
78 call add_real_3d("rcon0", ns, nzeta, ntheta3, rcon0 )
79 call add_real_3d("zcon0", ns, nzeta, ntheta3, zcon0 )
80 call add_real_3d("gcon", ns, nzeta, ntheta3, gcon )
81
82 call add_real_4d("r1", ns, 2, nzeta, ntheta3, r1, order=(/ 1, 3, 4, 2 /) )
83 call add_real_4d("z1", ns, 2, nzeta, ntheta3, z1, order=(/ 1, 3, 4, 2 /) )
84 call add_real_4d("ru", ns, 2, nzeta, ntheta3, ru, order=(/ 1, 3, 4, 2 /) )
85 call add_real_4d("zu", ns, 2, nzeta, ntheta3, zu, order=(/ 1, 3, 4, 2 /) )
86 call add_real_4d("rcon_in", ns, 2, nzeta, ntheta3, rcon, order=(/ 1, 3, 4, 2 /) )
87 call add_real_4d("zcon_in", ns, 2, nzeta, ntheta3, zcon, order=(/ 1, 3, 4, 2 /) )
88
89 if (lthreed) then
90 call add_real_4d("rv", ns, 2, nzeta, ntheta3, rv, order=(/ 1, 3, 4, 2 /) )
91 call add_real_4d("zv", ns, 2, nzeta, ntheta3, zv, order=(/ 1, 3, 4, 2 /) )
92 else
93 call add_null("rv")
94 call add_null("zv")
95 end if
96 end if ! dump_forces
97
98 ndim = 1+nrzt ! TODO: remove this; one extra element at the end of a large vector sound like reconstruction stuff...
99
100 ! POINTER ALIASES
101 bsqr => extra1(:,1) ! output or temp
102 gvvs => extra2(:,1) ! output or temp
103 guvs => extra3(:,1) ! output or temp
104 guus => extra4(:,1) ! output or temp
105
106 ! zero values at axis
107 lu_e(1:ndim:ns) = 0.0_dp ! fixup input
108 lv_e(1:ndim:ns) = 0.0_dp ! fixup input
109 guu(1:ndim:ns) = 0.0_dp ! fixup input
110 guv(1:ndim:ns) = 0.0_dp ! fixup input
111 gvv(1:ndim:ns) = 0.0_dp ! fixup input
112
113 guus = guu*shalf ! output or temp
114 guvs = guv*shalf ! output or temp
115 gvvs = gvv*shalf ! output or temp
116
117 armn_e = ohs*zu12 * lu_e ! output or temp
118 azmn_e =-ohs*ru12 * lu_e ! output or temp
119 brmn_e = brmn_e * lu_e ! output or temp
120 bzmn_e =-bzmn_e * lu_e ! output or temp
121 bsqr = dshalfds*lu_e/shalf ! output or temp
122
123 armn_o(1:ndim) = armn_e(1:ndim) *shalf ! output or temp
124 azmn_o(1:ndim) = azmn_e(1:ndim) *shalf ! output or temp
125 brmn_o(1:ndim) = brmn_e(1:ndim) *shalf ! output or temp
126 bzmn_o(1:ndim) = bzmn_e(1:ndim) *shalf ! output or temp
127
128 ! CONSTRUCT CYLINDRICAL FORCE KERNELS
129 ! NOTE: presg(ns+1) == 0, AND WILL BE "FILLED IN" AT EDGE FOR FREE-BOUNDARY BY RBSQ
130 DO l = 1, nrzt
131 guu(l) = p5*(guu(l) + guu(l+1))
132 gvv(l) = p5*(gvv(l) + gvv(l+1))
133 bsqr(l) = bsqr(l) + bsqr(l+1)
134 guus(l) = p5*(guus(l) + guus(l+1))
135 gvvs(l) = p5*(gvvs(l) + gvvs(l+1))
136 armn_e(l) = armn_e(l+1) - armn_e(l) + p5*(lv_e(l) + lv_e(l+1))
137 azmn_e(l) = azmn_e(l+1) - azmn_e(l)
138 brmn_e(l) = p5*(brmn_e(l) + brmn_e(l+1))
139 bzmn_e(l) = p5*(bzmn_e(l) + bzmn_e(l+1))
140 END DO
141
142 armn_e(:nrzt) = armn_e(:nrzt) - (gvvs(:nrzt)*r1(:nrzt,1) + gvv(:nrzt)*r1(:nrzt,0))
143 brmn_e(:nrzt) = brmn_e(:nrzt) + bsqr(:nrzt)*z1(:nrzt,1) - (guus(:nrzt)*ru(:nrzt,1) + guu(:nrzt)*ru(:nrzt,0))
144 bzmn_e(:nrzt) = bzmn_e(:nrzt) - (bsqr(:nrzt)*r1(:nrzt,1) + guus(:nrzt)*zu(:nrzt,1) + guu(:nrzt)*zu(:nrzt,0))
145 lv_e(1:ndim) = lv_e(1:ndim)*shalf(1:ndim)
146 lu_o(1:ndim) = dshalfds*lu_e(1:ndim)
147
148 DO l = 1, nrzt
149 armn_o(l) = armn_o(l+1) - armn_o(l) - zu(l,0)*bsqr(l) + p5*(lv_e(l) + lv_e(l+1))
150 azmn_o(l) = azmn_o(l+1) - azmn_o(l) + ru(l,0)*bsqr(l)
151 brmn_o(l) = p5*(brmn_o(l) + brmn_o(l+1))
152 bzmn_o(l) = p5*(bzmn_o(l) + bzmn_o(l+1))
153 lu_o(l) = lu_o(l) + lu_o(l+1)
154 END DO
155
156 if (dbg_forces) then
157 ! save data before it gets overwritten again
158 ! due to array re-usage
159
160 call add_real_3d("lu_o", ns, nzeta, ntheta3, lu_o )
161 call add_real_3d("lv_e_out", ns, nzeta, ntheta3, lv_e )
162 end if
163
164 guu(1:nrzt) = guu(1:nrzt) * sqrts(1:nrzt)**2
165 bsqr(1:nrzt) = gvv(1:nrzt) * sqrts(1:nrzt)**2
166
167 armn_o(:nrzt) = armn_o(:nrzt) - (zu(:nrzt,1)*lu_o(:nrzt) + bsqr(:nrzt)*r1(:nrzt,1) + gvvs(:nrzt)*r1(:nrzt,0))
168 azmn_o(:nrzt) = azmn_o(:nrzt) + ru(:nrzt,1)*lu_o(:nrzt)
169 brmn_o(:nrzt) = brmn_o(:nrzt) + z1(:nrzt,1)*lu_o(:nrzt) - (guu(:nrzt)*ru(:nrzt,1) + guus(:nrzt)*ru(:nrzt,0))
170 bzmn_o(:nrzt) = bzmn_o(:nrzt) - (r1(:nrzt,1)*lu_o(:nrzt) + guu(:nrzt)*zu(:nrzt,1) + guus(:nrzt)*zu(:nrzt,0))
171
172 IF (lthreed) THEN
173 DO l = 1, nrzt
174 guv(l) = p5*(guv(l) + guv(l+1))
175 guvs(l) = p5*(guvs(l) + guvs(l+1))
176 END DO
177
178 brmn_e(:nrzt) = brmn_e(:nrzt) - (guv(:nrzt)*rv(:nrzt,0) + guvs(:nrzt)*rv(:nrzt,1))
179 bzmn_e(:nrzt) = bzmn_e(:nrzt) - (guv(:nrzt)*zv(:nrzt,0) + guvs(:nrzt)*zv(:nrzt,1))
180 crmn_e(:nrzt) = guv(:nrzt) *ru(:nrzt,0) + gvv(:nrzt) *rv(:nrzt,0) + gvvs(:nrzt)*rv(:nrzt,1) + guvs(:nrzt)*ru(:nrzt,1)
181 czmn_e(:nrzt) = guv(:nrzt) *zu(:nrzt,0) + gvv(:nrzt) *zv(:nrzt,0) + gvvs(:nrzt)*zv(:nrzt,1) + guvs(:nrzt)*zu(:nrzt,1)
182
183 guv(:nrzt) = guv(:nrzt) * sqrts(:nrzt)*sqrts(:nrzt)
184
185 brmn_o(:nrzt) = brmn_o(:nrzt) - (guvs(:nrzt)*rv(:nrzt,0) + guv(:nrzt)*rv(:nrzt,1))
186 bzmn_o(:nrzt) = bzmn_o(:nrzt) - (guvs(:nrzt)*zv(:nrzt,0) + guv(:nrzt)*zv(:nrzt,1))
187 crmn_o(:nrzt) = guvs(:nrzt)*ru(:nrzt,0) + gvvs(:nrzt)*rv(:nrzt,0) + bsqr(:nrzt)*rv(:nrzt,1) + guv(:nrzt) *ru(:nrzt,1)
188 czmn_o(:nrzt) = guvs(:nrzt)*zu(:nrzt,0) + gvvs(:nrzt)*zv(:nrzt,0) + bsqr(:nrzt)*zv(:nrzt,1) + guv(:nrzt) *zu(:nrzt,1)
189 ENDIF
190
191 ! ASSIGN EDGE FORCES (JS = NS) FOR FREE BOUNDARY CALCULATION
192 IF (ivac .ge. 1) THEN
193
194! if (ns.eq.16) then
195!
196! ! plasma forces on LCFS before vacuum contribution gets added
197! write(dump_filename2, 997) iter2, trim(input_extension)
198! 997 format('lcfsfp_',i5.5,'.',a)
199! open(unit=43, file=trim(dump_filename2), status="unknown")
200!
201! lk = ns
202! do l=1, nznt
203! write(43, *) armn_e(lk+(l-1)*nznt), &
204! armn_o(lk+(l-1)*nznt), &
205! azmn_e(lk+(l-1)*nznt), &
206! azmn_o(lk+(l-1)*nznt)
207! end do
208!
209! close(43)
210!
211!
212!
213!
214! write(dump_filename2, 998) iter2, trim(input_extension)
215! 998 format('vacforce_',i5.5,'.',a)
216! open(unit=43, file=trim(dump_filename2), status="unknown")
217!
218! do l=1, nznt
219! write(43, *) zu0(ns+(l-1)*nznt)*rbsq(l), &
220! -ru0(ns+(l-1)*nznt)*rbsq(l)
221! end do
222!
223! close(43)
224! end if
225
226
227
228 ! no need for sqrt(s) scaling of odd-m contributions,
229 ! since free-boundary contribution enters at LCFS where s=1 ==> sqrt(s)=1
230 armn_e(ns:nrzt:ns) = armn_e(ns:nrzt:ns) + zu0(ns:nrzt:ns)*rbsq(1:nznt)
231 armn_o(ns:nrzt:ns) = armn_o(ns:nrzt:ns) + zu0(ns:nrzt:ns)*rbsq(1:nznt)
232 azmn_e(ns:nrzt:ns) = azmn_e(ns:nrzt:ns) - ru0(ns:nrzt:ns)*rbsq(1:nznt)
233 azmn_o(ns:nrzt:ns) = azmn_o(ns:nrzt:ns) - ru0(ns:nrzt:ns)*rbsq(1:nznt)
234 ENDIF
235
236! #ifndef _HBANGLE
237 ! COMPUTE CONSTRAINT FORCE KERNELS
238 rcon(:nrzt,0) = (rcon(:nrzt,0) - rcon0(:nrzt)) * gcon(:nrzt)
239 zcon(:nrzt,0) = (zcon(:nrzt,0) - zcon0(:nrzt)) * gcon(:nrzt)
240
241 brmn_e(:nrzt) = brmn_e(:nrzt) + rcon(:nrzt,0)
242 bzmn_e(:nrzt) = bzmn_e(:nrzt) + zcon(:nrzt,0)
243 brmn_o(:nrzt) = brmn_o(:nrzt) + rcon(:nrzt,0) * sqrts(:nrzt)
244 bzmn_o(:nrzt) = bzmn_o(:nrzt) + zcon(:nrzt,0) * sqrts(:nrzt)
245
246 ! real-space B-type forces due to constraint only
247 brmn_e_con(:nrzt) = brmn_e_con(:nrzt) + rcon(:nrzt,0)
248 bzmn_e_con(:nrzt) = bzmn_e_con(:nrzt) + zcon(:nrzt,0)
249 brmn_o_con(:nrzt) = brmn_o_con(:nrzt) + rcon(:nrzt,0) * sqrts(:nrzt)
250 bzmn_o_con(:nrzt) = bzmn_o_con(:nrzt) + zcon(:nrzt,0) * sqrts(:nrzt)
251
252 rcon(:nrzt,0) = ru0(:nrzt) * gcon(:nrzt)
253 zcon(:nrzt,0) = zu0(:nrzt) * gcon(:nrzt)
254 rcon(:nrzt,1) = rcon(:nrzt,0) * sqrts(:nrzt)
255 zcon(:nrzt,1) = zcon(:nrzt,0) * sqrts(:nrzt)
256! #end /* ndef _HBANGLE */
257
258 if (dbg_forces) then
259 call add_real_3d("armn_e", ns, nzeta, ntheta3, armn_e)
260 call add_real_3d("armn_o", ns, nzeta, ntheta3, armn_o)
261 call add_real_3d("brmn_e", ns, nzeta, ntheta3, brmn_e)
262 call add_real_3d("brmn_o", ns, nzeta, ntheta3, brmn_o)
263 call add_real_3d("azmn_e", ns, nzeta, ntheta3, azmn_e)
264 call add_real_3d("azmn_o", ns, nzeta, ntheta3, azmn_o)
265 call add_real_3d("bzmn_e", ns, nzeta, ntheta3, bzmn_e)
266 call add_real_3d("bzmn_o", ns, nzeta, ntheta3, bzmn_o)
267 if (lthreed) then
268 call add_real_3d("crmn_e", ns, nzeta, ntheta3, crmn_e)
269 call add_real_3d("crmn_o", ns, nzeta, ntheta3, crmn_o)
270 call add_real_3d("czmn_e", ns, nzeta, ntheta3, czmn_e)
271 call add_real_3d("czmn_o", ns, nzeta, ntheta3, czmn_o)
272 else
273 call add_null("crmn_e")
274 call add_null("crmn_o")
275 call add_null("czmn_e")
276 call add_null("czmn_o")
277 end if
278
279 call add_real_3d("guu_out", ns, nzeta, ntheta3, guu )
280 call add_real_3d("guus", ns, nzeta, ntheta3, guus )
281 call add_real_3d("guv_out", ns, nzeta, ntheta3, guv )
282 call add_real_3d("guvs", ns, nzeta, ntheta3, guvs )
283 call add_real_3d("gvv_out", ns, nzeta, ntheta3, gvv )
284 call add_real_3d("gvvs", ns, nzeta, ntheta3, gvvs )
285 call add_real_3d("bsqr", ns, nzeta, ntheta3, bsqr )
286
287 call add_real_4d("rcon_out", ns, 2, nzeta, ntheta3, rcon, order=(/ 1, 3, 4, 2 /) )
288 call add_real_4d("zcon_out", ns, 2, nzeta, ntheta3, zcon, order=(/ 1, 3, 4, 2 /) )
289
290 call close_dbg_out()
291 end if
292
293END SUBROUTINE forces
subroutine forces
Compute the real-space MHD forces.
Definition forces.f90:7
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 rv
Definition realspace.f90:10
real(rprec), dimension(:), allocatable zu0
, even-m and odd-m added together appropriately
Definition realspace.f90:25
real(rprec), dimension(:,:), allocatable zv
Definition realspace.f90:13
real(rprec), dimension(:,:), allocatable zcon
spectral condensation term in
Definition realspace.f90:16
real(rprec), dimension(:,:), allocatable ru
Definition realspace.f90:9
real(rprec), dimension(:), allocatable gvv
metric element
Definition realspace.f90:22
real(rprec), dimension(:), allocatable sqrts
sqrt(s), two-dimensional array on full-grid
Definition realspace.f90:32
real(rprec), dimension(:,:), allocatable, target extra3
Definition realspace.f90:38
real(rprec), dimension(:), allocatable guv
metric element
Definition realspace.f90:21
real(rprec), dimension(:,:), allocatable, target extra4
Definition realspace.f90:39
real(rprec), dimension(:,:), allocatable, target extra1
Definition realspace.f90:36
real(rprec), dimension(:), allocatable shalf
sqrt(s) ,two-dimensional array on half-grid
Definition realspace.f90:31
real(rprec), dimension(:), allocatable ru0
, even-m and odd-m added together appropriately
Definition realspace.f90:24
real(rprec), dimension(:), allocatable gcon
spectral condensation force; "alias force"
Definition realspace.f90:27
real(rprec), dimension(:,:), allocatable, target z1
Definition realspace.f90:11
real(rprec), dimension(:,:), allocatable rcon
spectral condensation term in
Definition realspace.f90:15
real(rprec), dimension(:), allocatable rcon0
spectral condensation term in at start of current multi-grid iteration
Definition realspace.f90:17
real(rprec), dimension(:,:), allocatable r1
Definition realspace.f90:8
real(rprec), dimension(:), allocatable guu
metric element
Definition realspace.f90:20
real(rprec), dimension(:,:), allocatable, target extra2
Definition realspace.f90:37
real(rprec), dimension(:), allocatable zcon0
spectral condensation term in at start of current multi-grid iteration
Definition realspace.f90:18
real(rprec), dimension(:,:), allocatable zu
Definition realspace.f90:12
real(rprec), dimension(:), pointer bzmn_e_con
Definition vforces.f90:43
real(rprec), dimension(:), pointer azmn_o
Definition vforces.f90:27
real(rprec), dimension(:), pointer bzmn_e
Definition vforces.f90:28
real(rprec), dimension(:), pointer bzmn_o_con
Definition vforces.f90:44
real(rprec), dimension(:), pointer brmn_e
Definition vforces.f90:21
real(rprec), dimension(:), pointer brmn_e_con
Definition vforces.f90:41
real(rprec), dimension(:), pointer azmn_e
Definition vforces.f90:26
real(rprec), dimension(:), pointer czmn_e
Definition vforces.f90:30
real(rprec), dimension(:), pointer brmn_o_con
Definition vforces.f90:42
real(rprec), dimension(:), pointer brmn_o
Definition vforces.f90:22
real(rprec), dimension(:), pointer bzmn_o
Definition vforces.f90:29
real(rprec), dimension(:), pointer crmn_e
Definition vforces.f90:23
real(rprec), dimension(:), pointer czmn_o
Definition vforces.f90:31
real(rprec), dimension(:), pointer armn_o
Definition vforces.f90:20
real(rprec), dimension(:), pointer crmn_o
Definition vforces.f90:24
real(rprec), dimension(:), pointer armn_e
Definition vforces.f90:19
real(rprec) ohs
Definition vmec_main.f90:87
real(rprec), dimension(:), allocatable rbsq
integer ivac
counts number of free-boundary iterations
integer num_eqsolve_retries
logical lthreed