VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
vacuum.f90
Go to the documentation of this file.
1
3
23SUBROUTINE vacuum(rmnc, rmns, zmns, zmnc, xm, xn, &
24 plascur, rbtor, wint, ivac_skip, ivac, &
25 mnmax, ier_flag, lasym, signgs, &
26 raxis, zaxis)
27 USE vacmod
29 use vmec_main, only: input_extension
30
31 use dbgout
33
34 IMPLICIT NONE
35
36 INTEGER, intent(in) :: ivac_skip, mnmax
37 integer, intent(inout) :: ivac, ier_flag
38 REAL(rprec), intent(in) :: plascur, rbtor
39 REAL(rprec), DIMENSION(mnmax), INTENT(in) :: rmnc, rmns, zmns, zmnc, xm, xn
40 REAL(rprec), DIMENSION(nuv2), INTENT(in) :: wint
41 logical, intent(in) :: lasym
42 real(rprec), intent(in) :: signgs
43 real(rprec), dimension(nv), intent(in) :: raxis, zaxis
44
45 INTEGER :: mn, n, n1, m, i, info
46 REAL(rprec), DIMENSION(:), POINTER :: potcos, potsin
47 REAL(rprec):: dn2, dm2, cosmn, sinmn, huv, hvv, det, bsupu, bsupv, bsubuvac, fac
48 logical :: vac1n_solver_active
49
50 ! THIS ROUTINE COMPUTES .5 * B**2 ON THE VACUUM / PLASMA SURFACE
51 ! BASED ON THE PROGRAM BY P. MERKEL [J. Comp. Phys. 66, 83 (1986)]
52 ! AND MODIFIED BY W. I. VAN RIJ AND S. P. HIRSHMAN (1987)
53
54 ! THE USER MUST SUPPLY THE FILE << MGRID >> WHICH INCLUDES THE MAGNETIC
55 ! FIELD DATA TO BE READ BY THE SUBROUTINE BECOIL
56
57 ier_flag = norm_term_flag
58
59 raxis_nestor = raxis
60 zaxis_nestor = zaxis
61
62 IF (.not.ALLOCATED(potvac)) stop 'POTVAC not ALLOCATED in VACCUM'
63
64 ! INDEX OF LOCAL VARIABLES
65 !
66 ! rmnc,rmns,zmns,zmnc: Surface Fourier coefficients (m,n) of R,Z
67 ! xm,xn: m, n values corresponding to rc,zs array
68 ! bsqvac: B**2/2 at the vacuum INTERFACE
69 ! plascur: net toroidal current
70 ! rbtor : net (effective) poloidal current (loop integrated R*Btor)
71 ! mnmax: number of R, Z modes in Fourier series of R,Z
72 ! ivac_skip: regulates whether full (=0) or incremental (>0)
73 ! update of matrix elements is necessary
74
75 ! compute and store mean magnetic fields (due to
76 ! toroidal plasma current and EXTERNAL tf-coils)
77 ! note: these are fixed for a constant current iteration
78 !
79 ! bfield = rbtor*grad(zeta) + plascur*grad("theta") - grad(potential)
80 !
81 ! where "theta" is computed using Biot-Savart law for filaments
82 ! Here, the potential term is needed to satisfy B dot dS = 0 and has the form:
83 !
84 ! potential = SUM potsin*SIN(mu - nv) + potcos*COS(mu - nv)
85
86 ! write inputs to NESTOR
87 if (open_dbg_context("vac1n_vacuum", num_eqsolve_retries)) then
88
89 call add_real_1d("rmnc", mnmax, rmnc)
90 call add_real_1d("zmns", mnmax, zmns)
91 if (lasym) then
92 call add_real_1d("rmns", mnmax, rmns)
93 call add_real_1d("zmnc", mnmax, zmnc)
94 else
95 call add_null("rmns")
96 call add_null("zmnc")
97 end if
98 call add_real_1d("xm", mnmax, xm)
99 call add_real_1d("xn", mnmax, xn)
100
101 call add_real("plascur", plascur)
102 call add_real("rbtor", rbtor)
103
104 call add_real_2d("wint", nv, nu3, wint)
105
106 call add_int("ivac_skip", ivac_skip)
107 call add_int("ivac", ivac)
108 call add_int("mnmax", mnmax)
109 call add_int("ier_flag", ier_flag)
110 call add_logical("lasym", lasym)
111 call add_real("signgs", signgs)
112
113 call add_real_1d("raxis_nestor", nv, raxis_nestor)
114 call add_real_1d("zaxis_nestor", nv, zaxis_nestor)
115
116 call close_dbg_out()
117 end if
118
119 IF (.not. precal_done) then
120 CALL precal
121 end if
122 CALL surface (rmnc, rmns, zmns, zmnc, xm, xn, mnmax, lasym, signgs)
123 CALL bextern (plascur, wint)
124
125 ! NOTE: all fine up to here against NESTOR.py
126
127 ! Determine scalar magnetic potential POTVAC
128 CALL scalpot (potvac, amatrix, wint, ivac_skip, lasym, m_map_wrt, n_map_wrt)
129
130 ! stand-alone for debugging: working on scalpot at the moment
131 ! return
132
133 vac1n_solver_active = open_dbg_context("vac1n_solver", num_eqsolve_retries)
134 if (vac1n_solver_active) then
135 call add_real_2d("amatrix", mnpd2, mnpd2, amatrix)
136 call add_real_1d("potvac_in", mnpd2, potvac)
137 end if
138
139 CALL solver (amatrix, potvac, mnpd2, 1, info)
140 IF (info .ne. 0) stop 'Error in solver in VACUUM'
141
142 potsin => potvac(1:mnpd)
143 potcos => potvac(1+mnpd:)
144
145 if (vac1n_solver_active) then
146 call add_real_1d("potvac_out", mnpd2, potvac)
147
148 call close_dbg_out()
149 end if
150
151 ! compute tangential covariant (sub u,v) and contravariant
152 ! (super u,v) magnetic field components on the plasma surface
153 potu(:nuv2) = zero
154 potv(:nuv2) = zero
155
156 mn = 0
157 DO n = -nf, nf
158 dn2 = -(n*nfper)
159 n1 = abs(n)
160 DO m = 0, mf
161 mn = mn + 1
162 dm2 = m
163 DO i = 1, nuv2
164 cosmn = cosu1(i,m)*cosv1(i,n1) + csign(n)*sinu1(i,m)*sinv1(i,n1)
165 potu(i) = potu(i) + dm2*potsin(mn)*cosmn
166 potv(i) = potv(i) + dn2*potsin(mn)*cosmn
167 END DO
168 IF (lasym) then
169 DO i = 1, nuv2
170 sinmn = sinu1(i,m)*cosv1(i,n1) - csign(n)*cosu1(i,m)*sinv1(i,n1)
171 potu(i) = potu(i) - dm2*potcos(mn)*sinmn
172 potv(i) = potv(i) - dn2*potcos(mn)*sinmn
173 END DO
174 end if
175 END DO
176 END DO
177
178 DO i = 1, nuv2
179 ! Covariant components
180 bsubu(i) = potu(i) + bexu(i)
181 bsubv(i) = potv(i) + bexv(i)
182
183 huv = p5*guv_b(i)*(nfper)
184 hvv = gvv_b(i)*(nfper*nfper)
185 det = one/(guu_b(i)*hvv-huv*huv)
186
187 ! Contravariant components
188 bsupu = (hvv*bsubu(i)-huv*bsubv(i))*det
189 bsupv = ((-huv*bsubu(i))+guu_b(i)*bsubv(i))*det
190
191 ! .5*|Bvac|**2
192 bsqvac(i) = p5*(bsubu(i)*bsupu + bsubv(i)*bsupv)
193
194! if (ivac.eq.0) then
195! print *, i, bsqvac(i)
196! end if
197
198 ! cylindrical components of vacuum magnetic field
199 brv(i) = rub(i)*bsupu + rvb(i)*bsupv
200 bphiv(i) = r1b(i)*bsupv
201 bzv(i) = zub(i)*bsupu + zvb(i)*bsupv
202 END DO
203
204 if (open_dbg_context("vac1n_bsqvac", num_eqsolve_retries)) then
205
206 call add_real_1d("potsin", mnpd, potsin)
207 if (lasym) then
208 call add_real_1d("potcos", mnpd, potcos)
209 else
210 call add_null("potcos")
211 end if
212
213 call add_real_2d("potu", nv, nu3, potu)
214 call add_real_2d("potv", nv, nu3, potv)
215
216 call add_real_2d("bsubu", nv, nu3, bsubu)
217 call add_real_2d("bsubv", nv, nu3, bsubv)
218
219 call add_real_2d("bsqvac", nv, nu3, bsqvac)
220
221 call add_real_2d("brv", nv, nu3, brv)
222 call add_real_2d("bphiv", nv, nu3, bphiv)
223 call add_real_2d("bzv", nv, nu3, bzv)
224
225 call close_dbg_out()
226 end if
227
228 ! PRINT OUT VACUUM PARAMETERS
229 IF (ivac .eq. 0) THEN
230 ivac = ivac + 1
231
232 WRITE (*, 200) nfper, mf, nf, nu, nv
233 ! WRITE (nthreed, 200) nfper, mf, nf, nu, nv
234 200 FORMAT(/,2x,'In VACUUM, np =',i3,2x,'mf =',i3,2x,'nf =',i3,' nu =',i3,2x,'nv = ',i4)
235
236 ! -plasma current/pi2
237 bsubuvac = sum(bsubu(:nuv2)*wint(:nuv2))*signgs*pi2
238 bsubvvac = sum(bsubv(:nuv2)*wint(:nuv2))
239
240 fac = 1.e-6_dp/mu0 ! currents in MA
241 WRITE (*,1000) bsubuvac*fac, plascur*fac, bsubvvac, rbtor
242 ! WRITE (nthreed, 1000) bsubuvac*fac, plascur*fac, bsubvvac, rbtor
243 1000 FORMAT(2x,'2*pi * a * -BPOL(vac) = ',1p,e10.2, &
244 ' TOROIDAL CURRENT = ',e10.2,/,2x,'R * BTOR(vac) = ', &
245 e10.2,' R * BTOR(plasma) = ',e10.2)
246
247 IF (rbtor*bsubvvac .lt. zero) THEN
248 ! rbtor and bsubvvac must have the same sign
249 ier_flag = phiedge_error_flag
250 ENDIF
251
252 IF (abs((plascur - bsubuvac)/rbtor) .gt. 1.e-2_dp) THEN
253! ier_flag = 10 ! 'VAC-VMEC I_TOR MISMATCH : BOUNDARY MAY ENCLOSE EXT. COIL'
254 print *, 'VAC-VMEC I_TOR MISMATCH : BOUNDARY MAY ENCLOSE EXT. COIL'
255 ENDIF
256
257 ENDIF
258
259 !icall = icall + 1
260
261END SUBROUTINE vacuum
subroutine bextern(plascur, wint)
Compute the total magnetic field due to external coils and the net toroidal plasma current.
Definition bextern.f90:9
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 bsubv
Definition vacmod.f90:80
real(rprec), dimension(:), allocatable bsqvac
Definition vacmod.f90:43
real(rprec), dimension(:), allocatable zvb
Definition vacmod.f90:50
real(rprec), dimension(:), allocatable r1b
Definition vacmod.f90:45
real(rprec), dimension(:), allocatable zub
Definition vacmod.f90:49
real(rprec), dimension(:), allocatable bzv
Definition vacmod.f90:41
real(rprec), dimension(:), allocatable, target potvac
Definition vacmod.f90:29
real(rprec), dimension(:), allocatable brv
Definition vacmod.f90:39
real(rprec), dimension(:), allocatable rub
Definition vacmod.f90:46
real(rprec) bsubvvac
Definition vacmod.f90:16
real(rprec), dimension(:), allocatable rvb
Definition vacmod.f90:47
real(rprec), dimension(:), allocatable raxis_nestor
Definition vacmod.f90:75
real(rprec), dimension(:), allocatable guu_b
Definition vacmod.f90:66
real(rprec), dimension(:), allocatable bphiv
Definition vacmod.f90:40
real(rprec), dimension(:), allocatable zaxis_nestor
Definition vacmod.f90:76
real(rprec), dimension(:), allocatable gvv_b
Definition vacmod.f90:68
real(rprec), dimension(:), allocatable bexv
Definition vacmod.f90:53
real(rprec), parameter p5
Definition vacmod.f90:13
real(rprec), dimension(:), allocatable guv_b
Definition vacmod.f90:67
real(rprec), dimension(:), allocatable bsubu
Definition vacmod.f90:79
real(rprec) pi2
Definition vacmod.f90:17
real(rprec), dimension(:), allocatable n_map_wrt
Definition vacmod.f90:32
real(rprec), dimension(:), allocatable m_map_wrt
Definition vacmod.f90:31
logical precal_done
Definition vacmod.f90:27
real(rprec), dimension(:), allocatable amatrix
Definition vacmod.f90:83
real(rprec), dimension(:), allocatable potv
Definition vacmod.f90:82
real(rprec), dimension(:), allocatable bexu
Definition vacmod.f90:52
real(rprec), dimension(:), allocatable potu
Definition vacmod.f90:81
integer num_eqsolve_retries
integer, parameter phiedge_error_flag
integer, parameter norm_term_flag
subroutine precal
Pre-compute constant terms required for NESTOR.
Definition precal.f90:7
subroutine scalpot(bvec, amatrix, wint, ivacskip, lasym, m_map, n_map)
Compute all required terms for solving for the scalar magnetic potential.
Definition scalpot.f90:14
subroutine solver(amat, b, m, nrhs, info)
Solve a linear system of equations using dgesv.
Definition solver.f90:12
subroutine surface(rc, rs, zs, zc, xm, xn, mnmax, lasym, signgs)
Evaluate the geometry of the LCFS and tangential derivatives.
Definition surface.f90:16
subroutine vacuum(rmnc, rmns, zmns, zmnc, xm, xn, plascur, rbtor, wint, ivac_skip, ivac, mnmax, ier_flag, lasym, signgs, raxis, zaxis)
Compute the vacuum contribution to the free-boundary energy functional.
Definition vacuum.f90:27