VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
bcovar.f90
Go to the documentation of this file.
1
3
8SUBROUTINE bcovar (lu, lv)
9 USE vmec_main, fpsi => bvco, p5 => cp5
10 USE vmec_params, ONLY: ns4, signgs, pdamp, lamscale, ntmax, &
11 meven, modd
12 USE realspace
13 USE vforces, r12 => armn_o, ru12 => azmn_e, gsqrt => azmn_o, &
14 rs => bzmn_e, zs => brmn_e, zu12 => armn_e, &
15 bsubu_e => clmn_e, bsubv_e => blmn_e, &
16 bsubu_o => clmn_o, bsubv_o => blmn_o, &
17 bsq => bzmn_o, phipog => brmn_o
18 USE xstuff, ONLY: xc
19
20 use dbgout
21
22 IMPLICIT NONE
23
24 REAL(rprec), DIMENSION(nrzt,0:1), INTENT(inout) :: lu
25 REAL(rprec), DIMENSION(nrzt,0:1), INTENT(inout) :: lv
26
27 ! GENERALLY, IF TEMPORAL CONVERGENCE IS POOR, TRY TO INCREASE PDAMP (< 1) (STORED IN VMEC_PARAMS)
28
29 INTEGER :: l, js, ndim, lk, ku, m, n, rzl
30 REAL(rprec) :: r2, volume, curpol_temp
31
32 integer :: dim_j, dim_k, dim_l, linear_index
33
34! #ifndef _HBANGLE
35 REAL(rprec) :: arnorm, aznorm, tcon_mul
36! #end /* ndef _HBANGLE */
37
38 REAL(rprec), POINTER, DIMENSION(:) :: luu, luv, lvv, tau
39 REAL(rprec), DIMENSION(:), POINTER :: bsupu, bsubuh, bsupv, bsubvh, r12sq
40
41 ndim = 1+nrzt ! what is hidden at the end of these vectors? probably leftover from reconstruction stuff...
42
43 ! POINTER ALIAS ASSIGNMENTS
44 tau => extra1(:,1)
45 luu => extra2(:,1)
46 luv => extra3(:,1)
47 lvv => extra4(:,1)
48
49 bsupu => luu
50 bsupv => luv
51 bsubuh => bsubu_o
52 bsubvh => bsubv_o
53 r12sq => bsq
54
55 guu(ndim) = 0 ! TODO: can probably go away if last element is not used anyway...
56 guv = 0
57 gvv = 0
58
59 ! COMPUTE METRIC ELEMENTS GIJ ON HALF MESH
60 ! FIRST, GIJ = EVEN PART (ON FULL MESH), LIJ = ODD PART (ON FULL MESH)
61 ! THEN, GIJ(HALF) = < GIJ(even)> + SHALF < GIJ(odd) >
62 r12sq(1:nrzt) = sqrts(1:nrzt)*sqrts(1:nrzt) ! s on full grid
63 guu(1:nrzt) = ru(1:nrzt,meven)*ru(1:nrzt,meven) &
64 + zu(1:nrzt,meven)*zu(1:nrzt,meven) + r12sq(1:nrzt)* &
65 ( ru(1:nrzt,modd )*ru(1:nrzt,modd ) &
66 + zu(1:nrzt,modd )*zu(1:nrzt,modd ))
67
68 luu(1:nrzt) = ( ru(1:nrzt,meven)*ru(1:nrzt,modd) &
69 + zu(1:nrzt,meven)*zu(1:nrzt,modd))*2.0_dp
70
71 ! temporary re-use of phipog for contribution to g_vv^o from R^2
72 phipog(1:nrzt)= 2.0_dp * r1(1:nrzt,meven)*r1(1:nrzt,modd)
73 !do l=1,2*ns
74 ! print *, l, r1(l,meven), r1(l,modd), phipog(l)
75 !end do
76
77 IF (lthreed) THEN
78 guv(1:nrzt) = ru(1:nrzt,meven)*rv(1:nrzt,meven) &
79 + zu(1:nrzt,meven)*zv(1:nrzt,meven) + r12sq(1:nrzt)* &
80 ( ru(1:nrzt,modd )*rv(1:nrzt,modd ) &
81 + zu(1:nrzt,modd )*zv(1:nrzt,modd ) )
82 luv(1:nrzt) = ru(1:nrzt,meven)*rv(1:nrzt,modd ) &
83 + ru(1:nrzt,modd )*rv(1:nrzt,meven) &
84 + zu(1:nrzt,meven)*zv(1:nrzt,modd ) &
85 + zu(1:nrzt,modd )*zv(1:nrzt,meven)
86
87 gvv(1:nrzt) = rv(1:nrzt,meven)*rv(1:nrzt,meven) &
88 + zv(1:nrzt,meven)*zv(1:nrzt,meven) + r12sq(1:nrzt)* &
89 ( rv(1:nrzt,modd )*rv(1:nrzt,modd ) &
90 + zv(1:nrzt,modd )*zv(1:nrzt,modd ) )
91 lvv(1:nrzt) =(rv(1:nrzt,meven)*rv(1:nrzt,modd ) &
92 + zv(1:nrzt,meven)*zv(1:nrzt,modd ))*2.0_dp
93 END IF
94
95 ! contribution to g_vv^e from R^2
96 r12sq(1:nrzt) = r1(1:nrzt,meven)*r1(1:nrzt,meven) + r12sq(1:nrzt)* &
97 r1(1:nrzt,modd )*r1(1:nrzt,modd )
98
99 ! need to do this in reverse order since guu and r12sq were re-used
100 ! for their full-grid even-m contributions
101 DO l = nrzt, 2, -1
102 guu(l) = p5*(guu(l) + guu(l-1) + shalf(l)*(luu(l) + luu(l-1)))
103 ! g_uu done here
104
105! if (mod(l-1,ns).eq.0) then
106! print *, (l-1)/ns+1, l, "evn_contrib=",p5*( r12sq(l) + r12sq(l-1) )," from ", r12sq(l)," and ", r12sq(l-1)
107! print *, (l-1)/ns+1, l, "odd_contrib=",p5*( phipog(l) + phipog(l-1) )," from ",phipog(l)," and ",phipog(l-1)
108! end if
109 ! r12sq = R^2 for g_vv here
110 r12sq(l) = p5*( r12sq(l) + r12sq(l-1) + shalf(l)*(phipog(l) + phipog(l-1)) )
111 END DO
112
113 IF (lthreed) THEN
114 DO l = nrzt, 2, -1
115 guv(l) = p5*(guv(l) + guv(l-1) + shalf(l)*(luv(l) + luv(l-1)))
116 gvv(l) = p5*(gvv(l) + gvv(l-1) + shalf(l)*(lvv(l) + lvv(l-1)))
117 END DO
118 END IF
119
120 ! save tau as output from jacobian()
121 ! TODO: for what later use is tau needed separately ?
122 tau(1:nrzt) = gsqrt(1:nrzt)
123
124 ! actually build \sqrt{g} now with tau from jacobian()
125 ! and R^2 on the half-mesh from jacobian() as well
126 gsqrt(1:nrzt) = r12(1:nrzt)*tau(1:nrzt) ! r12 = R on half grid
127
128 ! constant extrapolation of sqrt(g) towards axis
129 ! TODO: or does this overwrite the weird terms at the ghost surface outside the LCFS ???
130 gsqrt(1:nrzt:ns) = gsqrt(2:nrzt:ns)
131
132 ! g_vv contains all up to R^2 here; so add R^2 term now
133 gvv(2:nrzt) = gvv(2:nrzt) + r12sq(2:nrzt)
134
135 if (open_dbg_context("metric", num_eqsolve_retries)) then
136
137 call add_real_3d("gsqrt", ns, nzeta, ntheta3, gsqrt)
138 call add_real_3d("guu", ns, nzeta, ntheta3, guu )
139 call add_real_3d("r12sq", ns, nzeta, ntheta3, r12sq)
140 call add_real_3d("gvv", ns, nzeta, ntheta3, gvv )
141
142 if (lthreed) then
143 call add_real_3d("guv", ns, nzeta, ntheta3, guv )
144 else
145 call add_null("guv")
146 end if
147
148 call close_dbg_out()
149 end if
150
151 ! CATCH THIS AFTER WHERE LINE BELOW phipog = 0
152
153 ! this is where phipog == 1/sqrt(g) is actually assigned
154 ! note that the phip factor in phipog is gone... (see comment below)
155 WHERE (gsqrt(2:ndim) .ne. zero) phipog(2:ndim) = one/gsqrt(2:ndim)
156
157 ! 1/sqrt(g) is zero(since undefined) at the magnetic axis
158 phipog(1:ndim:ns) = 0.0_dp
159
160 ! compute plasma volume profile (vp) and total volume (voli)
161 vp(1) = 0.0_dp
162 vp(ns+1) = 0.0_dp
163 DO js = 2, ns
164 vp(js) = signgs*sum(gsqrt(js:nrzt:ns)*wint(js:nrzt:ns))
165 END DO
166
167 IF (iter2 .eq. 1) then
168 voli = twopi*twopi*hs*sum(vp(2:ns))
169 end if
170
171 ! check plasma volume computation
172 if (open_dbg_context("volume", num_eqsolve_retries)) then
173
174 call add_real_1d("vp", ns+1, vp)
175 call add_real("voli", voli)
176
177 call close_dbg_out()
178 end if
179
180 ! COMPUTE CONTRA-VARIANT COMPONENTS OF B (Bsupu,v) ON RADIAL HALF-MESH TO ACCOMODATE LRFP=T CASES.
181 ! THE OVERALL PHIP FACTOR (PRIOR TO v8.46) HAS BEEN REMOVED FROM PHIPOG, SO NOW PHIPOG == 1/GSQRT!
182 !
183 ! NOTE: LU = LAMU == d(LAM)/du, LV = -LAMV == -d(LAM)/dv COMING INTO THIS ROUTINE.
184 ! CHIP will be added IN CALL TO ADD_FLUXES.
185 ! THE NET BSUPU, BSUPV ARE (PHIPOG=1/GSQRT AS NOTED ABOVE):
186 !
187 ! BSUPU = PHIPOG*(chip - LAMV*LAMSCALE),
188 ! BSUPV = PHIPOG*(phip + LAMU*LAMSCALE)
189 lu = lu*lamscale
190 lv = lv*lamscale
191
192 DO js=1,ns
193 lu(js:nrzt:ns,0) = lu(js:nrzt:ns,0) + phipf(js)
194 END DO
195
196 bsupu(2:nrzt) = phipog(2:nrzt) * p5*( lv(2:nrzt,0) + lv(1:nrzt-1,0) &
197 + shalf(2:nrzt)*(lv(2:nrzt,1) + lv(1:nrzt-1,1)) )
198 bsupv(2:nrzt) = phipog(2:nrzt) * p5*( lu(2:nrzt,0) + lu(1:nrzt-1,0) &
199 + shalf(2:nrzt)*(lu(2:nrzt,1) + lu(1:nrzt-1,1)) )
200
201 ! first point at (u,v)=(0,0) on axis
202 bsupu(1)=0.0_dp
203 bsupv(1)=0.0_dp
204
205 ! v8.49: add ndim points --> TODO: likely not needed anymore, reconstruction-related?
206 bsupu(ndim)=0.0_dp
207 bsupv(ndim)=0.0_dp
208
209 if (open_dbg_context("bcontrav", num_eqsolve_retries)) then
210
211 call add_real_3d("bsupu", ns, nzeta, ntheta3, bsupu)
212 call add_real_3d("bsupv", ns, nzeta, ntheta3, bsupv)
213
214 call close_dbg_out()
215 end if
216
217 ! UPDATE IOTA EITHER OF TWO WAYS:
218 ! 1) FOR ictrl_prec2d = 0, SOLVE THE LINEAR ALGEBRAIC EQUATION <Bsubu> = icurv FOR iotas
219 ! 2) FOR ictrl_prec2d > 0, EVOLVE IOTAS IN TIME, USING Force-iota = <Bsubu> - icurv.
220 !
221 ! NEED TO DO IT WAY (#2) TO EASILY COMPUTE THE HESSIAN ELEMENTS DUE TO LAMBDA-VARIATIONS.
222 ! IOTAS IS "STORED" AT LOCATION LAMBDA-SC(0,0) IN XC-ARRAY [USE THIS COMPONENT SO IT
223 ! WILL WORK EVEN FOR 2D PLASMA], ALTHOUGH ITS VARIATION IS LIKE THAT OF LV-CS(0,0),
224 ! WITH N -> 1 IN THE HESSIAN CALCULATION ROUTINES (Compute_Hessian_Flam_lam, etc.)
225
226 ! COMPUTE (IF NEEDED) AND ADD CHIP TO BSUPU
227 CALL add_fluxes(phipog, bsupu, bsupv)
228
229 ! COMPUTE COVARIANT B COMPONENT bsubu,v (LAMBDA FORCE KERNELS) ON RADIAL HALF-MESH
230 bsubuh(1:nrzt) = guu(1:nrzt)*bsupu(1:nrzt) + guv(1:nrzt)*bsupv(1:nrzt)
231 bsubvh(1:nrzt) = guv(1:nrzt)*bsupu(1:nrzt) + gvv(1:nrzt)*bsupv(1:nrzt)
232
233 ! v8.49 --> TODO: likely not needed anymore, reconstruction-related?
234 bsubuh(ndim) = 0.0_dp
235 bsubvh(ndim) = 0.0_dp
236
237 ! COMPUTE MAGNETIC AND KINETIC PRESSURE ON RADIAL HALF-MESH
238 ! bsq = |B|^2/2 = 0.5*(B^u*B_u + B^v*B_v)
239 bsq(:nrzt) = p5*(bsupu(:nrzt)*bsubuh(:nrzt) + bsupv(:nrzt)*bsubvh(:nrzt))
240 pres(2:ns) = mass(2:ns)/vp(2:ns)**gamma
241
242 ! magnetic energy
243 wb = hs*abs(sum(wint(:nrzt)*gsqrt(:nrzt)*bsq(:nrzt)))
244
245 ! kinetic == thermal enery
246 wp = hs*sum(vp(2:ns)*pres(2:ns))
247
248! write(*,*) "magnetic energy: ", wb
249! write(*,*) "kinetic energy: ", wp
250
251 ! ADD KINETIC PRESSURE TO MAGNETIC PRESSURE
252 DO js=2,ns
253 bsq(js:nrzt:ns) = bsq(js:nrzt:ns) + pres(js)
254 END DO
255
256 if (open_dbg_context("bcov", num_eqsolve_retries)) then
257
258 call add_real_3d("bsubuh", ns, nzeta, ntheta3, bsubuh)
259 call add_real_3d("bsubvh", ns, nzeta, ntheta3, bsubvh)
260 call add_real_3d("bsq", ns, nzeta, ntheta3, bsq )
261
262 call add_real_1d("pres", ns-1, pres(2:ns))
263
264 call add_real("wb", wb)
265 call add_real("wp", wp)
266
267 call close_dbg_out()
268 end if
269
270 ! COMPUTE LAMBDA FULL MESH FORCES
271 ! NOTE: bsubu_e is used here ONLY as a temporary array (TODO: for what?)
272 lvv = phipog(:ndim)*gvv
273 bsubv_e(1:nrzt) = p5*(lvv(1:nrzt)+lvv(2:ndim))*lu(1:nrzt,0) ! already on full-grid
274
275! if (iter2.eq.2) then
276! write(*,*) "bsubv_e(1) first step: ", bsubv_e(1)
277! end if
278
279 lvv = lvv*shalf
280 bsubu_e(:nrzt) = guv(:nrzt)*bsupu(:nrzt)
281 bsubu_e(ndim) = 0
282
283! ! printout for comparison
284! do dim_j = 1, ns
285! do dim_k = 1, nzeta
286! do dim_l = 1, ntheta3
287! linear_index = ((dim_l-1) * nzeta + dim_k-1) * ns + dim_j-1 + 1
288! write(44, *) dim_j, dim_k, dim_l, &
289! ! bsubv_e(linear_index), &
290! p5*(lvv(linear_index) + lvv(linear_index+1)), & ! *lu(linear_index,1)
291! lu(linear_index,1)
292! end do ! dim_l
293! end do ! dim_k
294! end do ! dim_j
295!
296! if (iter2 .eq. 2) stop
297
298 bsubv_e(1:nrzt) = bsubv_e(1:nrzt) &
299 + p5*((lvv(1:nrzt) + lvv(2:ndim))*lu(1:nrzt,1) & ! interp to full grid done here
300 + bsubu_e(1:nrzt) + bsubu_e(2:ndim))
301
302! if (iter2.eq.2) then
303! write(*,*) "bsubu_e(1:2) = ", bsubu_e(1:2), " from ", &
304! guv(1:2), bsupu(1:2)
305! write(*,*) "bsubv_e(1) second step: ", bsubv_e(1), lvv(1), lvv(2), &
306! lu(1,1), bsubu_e(1), bsubu_e(2)
307! end if
308
309 if (open_dbg_context("lambda_forces", num_eqsolve_retries)) then
310
311 call add_real_3d("lvv", ns, nzeta, ntheta3, lvv )
312 call add_real_4d("lu", ns, 2, nzeta, ntheta3, lu, order=(/1, 3, 4, 2 /))
313 call add_real_3d("bsubu_e", ns, nzeta, ntheta3, bsubu_e)
314 call add_real_3d("bsubv_e", ns, nzeta, ntheta3, bsubv_e)
315
316 call close_dbg_out()
317 end if
318
319 ! COMPUTE AVERAGE FORCE BALANCE AND TOROIDAL/POLOIDAL CURRENTS
320 CALL calc_fbal(bsubuh, bsubvh)
321
322 ! fpsi is simply an alias to bvco (which is filled in calc_fbal)
323 ! --> why not use bvco here ???
324 ! This computes the poloidal current close to the axis (rbtor0)
325 ! and the poloidal current at the boundary (rbtor).
326 rbtor0= c1p5*fpsi(2) - p5*fpsi(3)
327 rbtor = c1p5*fpsi(ns) - p5*fpsi(ns-1)
328
329 ! (SPH:08/19/04)
330 ! MUST AVOID BREAKING TRI-DIAGONAL RADIAL COUPLING AT EDGE WHEN USING PRECONDITIONER
331 ! CTOR IS PASSED TO VACUUM TO COMPUTE EDGE BSQVAC, SO IT CAN ONLY DEPEND ON NS, NS-1
332 ! THUS, CTOR ~ buco(ns) WORKS, WITH REMAINDER A FIXED CONSTANT.
333 !
334 ! ALSO, IF USING FAST SWEEP IN COMPUTE_BLOCKS, MUST MAKE CTOR CONSTANT
335 ! TO AVOID BREAKING SYMMETRY OF A+(ns-1) AND B-(ns) HESSIAN ELEMENTS
336 !
337 ! TO GET CORRECT HESSIAN, USE THE CTOR=ctor_prec2d +... ASSIGNMENT
338 ! FOR ictrl_prec2d.ne.0 (replace ictrl_prec2d.gt.1 with ictrl_prec2d.ne.0 in IF test below)
339
340 ! NEXT COMPUTE COVARIANT BSUBV COMPONENT ~ lvv ON FULL RADIAL MESH BY AVERAGING HALF-MESH METRICS
341 ! NOTE: EDGE VALUES AT JS=NS DOWN BY 1/2
342 ! THIS IS NEEDED FOR NUMERICAL STABILITY
343
344 ! This computes the net toroidal current enclosed by the LCFS (ctor).
345 ctor = signgs*twopi*(c1p5*buco(ns) - p5*buco(ns1))
346
347 DO l=1,ns
348 lvv(l:nrzt:ns) = bdamp(l) ! --> profil1d()
349 ! blending parameter: 0.1 at the axis, ca. 0 at the LCFS
350 ! TODO: is it intentional that this is linked to pdamp (time-step algorithm) ?
351 END DO
352
353 ! COMMENTED OUT BY SAL --> why does this check hurt ?
354 ! IF (ANY(bsubuh(1:ndim:ns) .ne. zero)) STOP 'BSUBUH != 0 AT JS=1'
355 ! IF (ANY(bsubvh(1:ndim:ns) .ne. zero)) STOP 'BSUBVH != 0 AT JS=1'
356
357! ! printout for comparison
358! do dim_j = 1, ns
359! do dim_k = 1, nzeta
360! do dim_l = 1, ntheta3
361! linear_index = ((dim_l-1) * nzeta + dim_k-1) * ns + dim_j-1 + 1
362! write(44, *) dim_j, dim_k, dim_l, p5*(bsubvh(linear_index) + bsubvh(linear_index + 1)), bsubv_e(linear_index)
363! end do ! dim_l
364! end do ! dim_k
365! end do ! dim_j
366!
367! if (iter2 .eq. 2) stop
368
369 ! AVERAGE LAMBDA FORCES ONTO FULL RADIAL MESH
370 ! USE BLENDING FOR bsubv_e FOR NUMERICAL STABILITY NEAR AXIS
371 bsubu_e(1:nrzt) = p5* (bsubuh(1:nrzt) + bsubuh(2:ndim))
372 bsubv_e(1:nrzt) = lvv(1:nrzt) * bsubv_e(1:nrzt) &
373 + p5*(1-lvv(1:nrzt))*(bsubvh(1:nrzt) + bsubvh(2:ndim))
374
375 if (open_dbg_context("bcov_full", num_eqsolve_retries)) then
376
377 call add_real("rbtor0", rbtor0)
378 call add_real("rbtor", rbtor)
379 call add_real("ctor", ctor)
380
381 call add_real_1d("bdamp", ns, bdamp)
382
383 call add_real_3d("bsubu_e", ns, nzeta, ntheta3, bsubu_e)
384 call add_real_3d("bsubv_e", ns, nzeta, ntheta3, bsubv_e)
385
386 call close_dbg_out()
387 end if
388
389 if (iequi .eq. 0) then
390 ! COMPUTE R,Z AND LAMBDA PRE-CONDITIONING MATRIX ELEMENTS AND FORCE NORMS:
391
392 ! COMPUTE PRECONDITIONING (1D) AND SCALING PARAMETERS
393 ! NO NEED TO RECOMPUTE WHEN 2D-PRECONDITIONER ON
394 IF (mod(iter2-iter1,ns4).eq.0) THEN
395 ! only update preconditioner every ns4==25 iterations (?) (for ns4, see vmec_params)
396
397 ! write(*,*) "update 1d preconditioner at iter2=", iter2
398
399 phipog(:nrzt) = phipog(:nrzt)*wint(:nrzt) ! remember that actually phipog == 1/sqrt(g)
400
401 CALL lamcal(phipog, guu, guv, gvv)
402
403 CALL precondn(bsupv, bsq, gsqrt, r12, &
404 zs, zu12, zu, zu(1,1), z1(1,1), &
405 arm, ard, brm, brd, crd, cos01)
406
407 CALL precondn(bsupv, bsq, gsqrt, r12, &
408 rs, ru12, ru, ru(1,1), r1(1,1), &
409 azm, azd, bzm, bzd, crd, sin01)
410
411 ! check preconditioner output
412 if (open_dbg_context("precondn", num_eqsolve_retries)) then
413
414 call add_real_2d("arm", ns+1, 2, arm)
415 call add_real_2d("ard", ns+1, 2, ard)
416 call add_real_2d("brm", ns+1, 2, brm)
417 call add_real_2d("brd", ns+1, 2, brd)
418 call add_real_1d("crd", ns+1, crd)
419 call add_real_2d("azm", ns+1, 2, azm)
420 call add_real_2d("azd", ns+1, 2, azd)
421 call add_real_2d("bzm", ns+1, 2, bzm)
422 call add_real_2d("bzd", ns+1, 2, bzd)
423
424 call close_dbg_out()
425 end if
426
427 volume = hs*sum(vp(2:ns))
428
429 r2 = max(wb,wp)/volume ! energy density ???
430
432 guu(:nrzt) = guu(:nrzt)*r12(:nrzt)**2
433
435 fnorm = one/(sum(guu(1:nrzt)*wint(1:nrzt))*(r2*r2))
436
438 fnorm1 = one/sum(xc(1+ns:2*irzloff)**2)
439
441 fnorml = one/(sum((bsubuh(1:nrzt)**2 + bsubvh(1:nrzt)**2)*wint(1:nrzt))*lamscale**2)
442
443 ! r3 = one/(2*r0scale)**2
444 ! > Norm for preconditioned Lambda force
445 ! fnorm2 = one/MAX(SUM(xc(2*irzloff+1:3*irzloff)**2),r3/4)
446
447 ! COMPUTE CONSTRAINT FORCE SCALING FACTOR (TCON)
448 ! OVERRIDE USER INPUT VALUE HERE
449
450! #ifndef _HBANGLE
451 r2 = ns ! temporary re-use of variable for floating-point version of ns
452
453 ! ignore large tcon0 from old-style files
454 tcon0 = min(abs(tcon0), one)
455
456 ! some parabola in ns, but why these specific values of the parameters ?
457 tcon_mul = tcon0*(1 + r2*(one/60 + r2/(200*120)))
458
459 tcon_mul = tcon_mul/((4*r0scale**2)**2) ! Scaling of ard, azd (2*r0scale**2);
460 ! Scaling of cos**2 in alias (4*r0scale**2)
461
462! print *, "tcon_mul = ", tcon_mul
463
464 DO js = 2, ns-1
465 arnorm = sum(wint(js:nrzt:ns)*ru0(js:nrzt:ns)**2)
466 aznorm = sum(wint(js:nrzt:ns)*zu0(js:nrzt:ns)**2)
467 IF (arnorm.eq.zero .or. aznorm.eq.zero) then
468 stop 'arnorm or aznorm=0 in bcovar'
469 end if
470
471 tcon(js) = min(abs(ard(js,1)/arnorm), abs(azd(js,1)/aznorm)) * tcon_mul*(32*hs)**2
472 END DO
473
474! print *, "tcon profile: ", tcon
475
476 tcon(ns) = p5*tcon(ns-1)
477
478 !IF (lasym) tcon = p5*tcon
479! #end /* ndef _HBANGLE */
480
481 if (open_dbg_context("forceNorms_tcon", num_eqsolve_retries)) then
482
483 call add_real("volume", volume)
484 call add_real("r2", max(wb,wp)/volume)
485 call add_real("fnorm", fnorm)
486 call add_real("fnorm1", fnorm1)
487 call add_real("fnormL", fnorml)
488 call add_real("tcon0", tcon0)
489 call add_real("tcon_mul", tcon_mul)
490 call add_real_1d("tcon", ns-1, tcon(2:ns))
491
492 call add_real_3d("guu", ns, nzeta, ntheta3, guu)
493 call add_real_5d("xc", 3, ntmax, ns, ntor1, mpol, xc, order=(/ 3, 4, 5, 2, 1 /) )
494
495 call close_dbg_out()
496 end if
497
498 ENDIF ! MOD(iter2-iter1,ns4).eq.0
499
500 ! MINUS SIGN => HESSIAN DIAGONALS ARE POSITIVE
501 bsubu_e = -lamscale*bsubu_e
502 bsubv_e = -lamscale*bsubv_e
503 bsubu_o(:nrzt) = sqrts(:nrzt)*bsubu_e(:nrzt)
504 bsubv_o(:nrzt) = sqrts(:nrzt)*bsubv_e(:nrzt)
505
506 ! STORE LU * LV COMBINATIONS USED IN FORCES
507 lvv(2:nrzt) = gsqrt(2:nrzt)
508 guu(2:nrzt) = bsupu(2:nrzt)*bsupu(2:nrzt)*lvv(2:nrzt)
509 guv(2:nrzt) = bsupu(2:nrzt)*bsupv(2:nrzt)*lvv(2:nrzt)
510 gvv(2:nrzt) = bsupv(2:nrzt)*bsupv(2:nrzt)*lvv(2:nrzt)
511 lv(2:nrzt,0) = bsq(2:nrzt)*tau(2:nrzt)
512 lu(2:nrzt,0) = bsq(2:nrzt)*r12(2:nrzt)
513
514 if (open_dbg_context("lulv_comb", num_eqsolve_retries)) then
515
516 call add_real_3d("bsubu_e", ns, nzeta, ntheta3, bsubu_e )
517 call add_real_3d("bsubv_e", ns, nzeta, ntheta3, bsubv_e )
518 call add_real_3d("bsubu_o", ns, nzeta, ntheta3, bsubu_o )
519 call add_real_3d("bsubv_o", ns, nzeta, ntheta3, bsubv_o )
520 call add_real_3d("lvv", ns, nzeta, ntheta3, lvv )
521 call add_real_3d("guu", ns, nzeta, ntheta3, guu )
522 call add_real_3d("guv", ns, nzeta, ntheta3, guv )
523 call add_real_3d("gvv", ns, nzeta, ntheta3, gvv )
524 call add_real_4d("lv", ns, 2, nzeta, ntheta3, lv, order=(/1, 3, 4, 2 /))
525 call add_real_4d("lu", ns, 2, nzeta, ntheta3, lu, order=(/1, 3, 4, 2 /))
526
527 call close_dbg_out()
528 end if
529
530 ELSE ! (iequi .eq. 0)
531
532 ! iequi == 1 --> final iter for fileout()
533
534 ! NOTE THAT lu=>czmn, lv=>crmn externally
535 ! SO THIS STORES bsupv in czmn_e, bsupu in crmn_e
536 ! only executed at end of equilibrium
537 lu(:nrzt,0) = bsupv(:nrzt)
538 lv(:nrzt,0) = bsupu(:nrzt)
539
540 ! COMPUTE COVARIANT BSUBU,V (EVEN, ODD) ON HALF RADIAL MESH
541 ! FOR FORCE BALANCE AND RETURN (IEQUI=1)
542
543 ! final call from fileout --> compute additional stuff
544 DO js = ns-1,2,-1 ! from the ~edge inward
545 DO l = js, nrzt, ns ! every grid point on the flux surfaces
546 bsubvh(l) = 2*bsubv_e(l) - bsubvh(l+1)
547 END DO
548 END DO
549
550 ! ADJUST <bsubvh> AFTER MESH-BLENDING
551 DO js = 2, ns ! local on half-grid?
552 curpol_temp = fpsi(js) - sum(bsubvh(js:nrzt:ns)*wint(js:nrzt:ns))
553
554 DO l = js, nrzt, ns ! all grid points on flux surface
555 bsubvh(l) = bsubvh(l) + curpol_temp
556 END DO
557 END DO
558
559 ! NOTE: below four lines modify bsubvh above !!!
560 bsubu_e(:nrzt) = bsubuh(:nrzt)
561 bsubv_e(:nrzt) = bsubvh(:nrzt)
562
563 bsubu_o(:nrzt) = shalf(:nrzt)*bsubu_e(:nrzt) ! will be undone again in jxbforce...
564 bsubv_o(:nrzt) = shalf(:nrzt)*bsubv_e(:nrzt)
565
566 if (open_dbg_context("bcovar_fileout", id=0)) then
567
568 call add_real_3d("lu_e", ns, nzeta, ntheta3, lu(:nrzt,0))
569 call add_real_3d("lv_e", ns, nzeta, ntheta3, lv(:nrzt,0))
570
571 call add_real_1d("fpsi", ns-1, fpsi(2:ns))
572
573! call add_real_3d("bsubvh", ns, nzeta, ntheta3, bsubvh)
574
575 call add_real_3d("bsubu_e", ns, nzeta, ntheta3, bsubu_e)
576 call add_real_3d("bsubv_e", ns, nzeta, ntheta3, bsubv_e)
577
578 call add_real_3d("bsubu_o", ns, nzeta, ntheta3, bsubu_o)
579 call add_real_3d("bsubv_o", ns, nzeta, ntheta3, bsubv_o)
580
581 call close_dbg_out()
582 end if
583
584 END IF ! (iequi .eq. 0)
585
586END SUBROUTINE bcovar
subroutine add_fluxes(overg, bsupu, bsupv)
Add the magnetic fluxes to the tangential derivatives of to arrive at the contravariant magnetic fie...
subroutine bcovar(lu, lv)
Compute the covariant components of the magnetic field , .
Definition bcovar.f90:9
subroutine calc_fbal(bsubu, bsubv)
Compute flux-surface averaged radial force balance .
Definition calc_fbal.f90:9
subroutine lamcal(overg, guu, guv, gvv)
Normalization parameters for .
Definition lamcal.f90:11
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 wint
two-dimensional array for normalizing angle integrations
Definition realspace.f90:34
real(rprec), dimension(:,:), allocatable zv
Definition realspace.f90:13
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, target z1
Definition realspace.f90:11
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 zu
Definition realspace.f90:12
real(rprec), dimension(:), pointer azmn_o
Definition vforces.f90:27
real(rprec), dimension(:), pointer bzmn_e
Definition vforces.f90:28
real(rprec), dimension(:), pointer clmn_o
Definition vforces.f90:36
real(rprec), dimension(:), pointer brmn_e
Definition vforces.f90:21
real(rprec), dimension(:), pointer azmn_e
Definition vforces.f90:26
real(rprec), dimension(:), pointer brmn_o
Definition vforces.f90:22
real(rprec), dimension(:), pointer clmn_e
Definition vforces.f90:35
real(rprec), dimension(:), pointer bzmn_o
Definition vforces.f90:29
real(rprec), dimension(:), pointer blmn_e
Definition vforces.f90:33
real(rprec), dimension(:), pointer armn_o
Definition vforces.f90:20
real(rprec), dimension(:), pointer armn_e
Definition vforces.f90:19
real(rprec), dimension(:), pointer blmn_o
Definition vforces.f90:34
integer irzloff
offset in xc array between R,Z,L components
real(rprec) rbtor
poloidal current at LCFS
real(rprec), dimension(:), allocatable vp
radial derivative of enclosed volume
Definition vmec_main.f90:56
real(rprec), dimension(:), allocatable bvco
enclosed poloidal current profile
Definition vmec_main.f90:43
real(rprec), dimension(:), allocatable buco
enclosed toroidal current profile
Definition vmec_main.f90:42
real(rprec), dimension(:), allocatable crd
Definition vmec_main.f90:24
real(rprec), dimension(:,:), allocatable brd
Definition vmec_main.f90:18
real(rprec) wp
kinetic/thermal energy (from pressure)
real(rprec) hs
radial mesh size increment
Definition vmec_main.f90:84
real(rprec), dimension(:,:), allocatable azd
Definition vmec_main.f90:20
integer iter1
number of iterations at which the currently active evolution was branched off from
real(rprec) ctor
toroidal current (?)
real(rprec) fnorm
Definition vmec_main.f90:93
real(rprec) voli
total plasma volume in m^3
Definition vmec_main.f90:88
real(rprec), dimension(:), allocatable bdamp
radial mesh-blending factor
Definition vmec_main.f90:27
integer iequi
counter used to call -EQFOR- at end of run
real(rprec), dimension(:,:), allocatable brm
Definition vmec_main.f90:19
real(rprec), dimension(:,:), allocatable bzd
Definition vmec_main.f90:22
real(rprec), dimension(:,:), allocatable bzm
Definition vmec_main.f90:23
real(rprec) fnorml
Definition vmec_main.f90:98
real(rprec) rbtor0
poloidal current at magnetic axis
real(rprec), dimension(:,:), allocatable ard
Definition vmec_main.f90:16
real(rprec), dimension(:), allocatable pres
pressure profile
Definition vmec_main.f90:55
real(rprec) wb
magnetic energy: volume integral over B^2/2
integer num_eqsolve_retries
real(rprec) fnorm1
Definition vmec_main.f90:97
real(rprec), dimension(:,:), allocatable arm
Definition vmec_main.f90:17
logical lthreed
real(rprec) r0scale
Definition vmec_main.f90:90
real(rprec), dimension(:), allocatable mass
mass profile on half-grid
Definition vmec_main.f90:71
integer iter2
total number of iterations
real(rprec), dimension(:,:), allocatable azm
Definition vmec_main.f90:21
real(rprec), dimension(:), allocatable phipf
radial derivative of toroidal magnetic flux (full grid)
Definition vmec_main.f90:35
real(rprec), dimension(:), allocatable tcon
constraint-force multiplier
Definition vmec_main.f90:47
real(rprec) signgs
sign of Jacobian : must be =1 (right-handed) or =-1 (left-handed)
real(rprec), parameter pdamp
integer, parameter modd
parity selection label for odd poloidal modes of R and Z
integer, parameter ns4
real(rprec) lamscale
integer ntmax
number of contributing Fourier basis function (can be 1, 2 or 4); assigned in read_indata()
integer, parameter meven
parity selection label for even poloidal modes of R and Z
real(rprec), dimension(:), allocatable, target xc
stacked array of scaled R, Z, Lambda Fourier coefficients (see above for stack order)
Definition xstuff.f90:40
subroutine precondn(lu1, bsq, gsqrt, r12, xs, xu12, xue, xuo, xodd, axm, axd, bxm, bxd, cx, trigmult)
Compute preconditioning matrix elements for , force.
Definition precondn.f90:27