VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
profil1d.f90
Go to the documentation of this file.
1
3
9SUBROUTINE profil1d()
10 USE vmec_main
11 USE vmec_params, ONLY: signgs, lamscale, rcc, pdamp
12 USE realspace, ONLY: shalf, sqrts
13
14 use dbgout
15
16 IMPLICIT NONE
17
18 INTEGER :: i
19 REAL(rprec) :: Itor, si, tf, pedge, vpnorm, torflux_edge, polflux_edge
20
21 REAL(rprec), EXTERNAL :: pcurr, pmass, piota, &
22 torflux, torflux_deriv, polflux, polflux_deriv
23
24 ! COMPUTE PHIP, IOTA PROFILES ON FULL-GRID
25 ! COMPUTE MASS PROFILE ON HALF-GRID BY READING INPUT COEFFICIENTS.
26 ! PRESSURE CONVERTED TO INTERNAL UNITS BY MULTIPLICATION BY mu0 = 4*pi*10**-7
27
28 torflux_edge = signgs * phiedge / twopi
29 si = torflux(one)
30 IF (si .ne. zero) torflux_edge = torflux_edge/si
31
32 polflux_edge = torflux_edge
33 si = polflux(one)
34 IF (si .ne. zero) polflux_edge = polflux_edge/si
35
36 ! z00 gets assiged in reset_params and in funct3d
37 r00 = rmn_bdy(0,0,rcc)
38
39 ! zero fluxes and current at magnetic axis
40 phips(1) = 0.0_dp
41 chips(1) = 0.0_dp
42 icurv(1) = 0.0_dp
43
44 ! half-grid quantities: s_i are shifted inwards by 0.5 grid points
45 DO i = 2,ns
46 si = hs*(i-c1p5)
47 tf = min(one, torflux(si))
48 phips(i) = torflux_edge * torflux_deriv(si)
49 chips(i) = torflux_edge * polflux_deriv(si)
50 iotas(i) = piota(tf) ! evaluate iota profile
51 icurv(i) = pcurr(tf) ! evaluate current profile
52 END DO
53 phips(ns+1) = 2.0_dp*phips(ns)-phips(ns-1) ! virtual point outside the LCFS
54
55 ! Compute lamscale factor for "normalizing" lambda (needed for scaling hessian)
56 lamscale = sqrt(hs*sum(phips(2:ns)**2.0_dp))
57 IF (lamscale .EQ. 0.0_dp) stop 'PHIP == 0: ERROR!'
58
59 IF (lflip) THEN
60 iotas = -iotas
61 chips = -chips
62 END IF
63
64 ! full-grid quantities
65 DO i = 1,ns
66 si = hs*(i-1.0_dp)
67 tf = min(one, torflux(si))
68 phipf(i) = torflux_edge * torflux_deriv(si)
69 chipf(i) = torflux_edge * polflux_deriv(si)
70 iotaf(i) = piota(tf)
71 ENDDO
72
73 ! SCALE CURRENT TO MATCH INPUT EDGE VALUE, CURTOR
74 ! FACTOR OF SIGNGS NEEDED HERE, SINCE MATCH IS MADE TO LINE
75 ! INTEGRAL OF BSUBU (IN GETIOTA) ~ SIGNGS * CURTOR
76 pedge = pcurr(one) ! pcurr gives current enclosed between axis and given parameter
77 ! --> pedge is temporarily re-used to store the radial integral over current density profile (still in Amperes)
78 itor = 0
79 ! TODO: what is this? might have something to do with preventing division-by-zero
80 ! when computing scaled toroidal current profile from pcurr and curtor...
81 IF (abs(pedge) .gt. abs(epsilon(pedge)*curtor)) then
82 itor = signgs*currv/(twopi*pedge)
83 end if
84 icurv(2:ns) = itor*icurv(2:ns)
85
86 ! POSSIBLE PRESSURE PEDESTAL FOR S >= SPRES_PED
87 spres_ped = abs(spres_ped)
88 DO i = 2,ns
89 si = hs*(i - c1p5)
90 ! NORMALIZE mass so dV/dPHI (or dV/dPSI) in pressure to mass relation
91 ! See line 195 of bcovar: pres(2:ns) = mass(2:ns)/vp(2:ns)**gamma
92 tf = min(one, torflux(si))
93 vpnorm = torflux_edge * torflux_deriv(si)
94
95 ! should either check if tf .gt. tf_pres_ped
96 ! or eval pmass at min(1, torflux(spres_ped))
97 ! for consistency ...
98 ! Also, pedge is re-used here; this actually is the pressure in the whole volume...
99 IF (si .gt. spres_ped) THEN
100 pedge = pmass(spres_ped)
101 ELSE
102 pedge = pmass(tf)
103 END IF
104 mass(i) = pedge*(abs(vpnorm)*r00)**gamma
105 END DO
106
107 pres(:ns+1) = 0.0_dp
108
109 DO i = 1, ns
110
111 ! sqrt(s_i) for half-grid s values (shifted inwards by -0.5 grid points)
112 si = hs*abs(i-1.5_dp)
113 shalf(i:nrzt:ns) = sqrt(si)
114
115 ! sqrt(s_i) for full-grid s values
116 si = hs*(i-1.0_dp)
117 sqrts(i:nrzt:ns) = sqrt(si)
118
119 ! TODO: what is this _exactly_?
120 ! just observing, this is a linear profile on the half-grid
121 ! which is at 2*pdamp == 0.1 at the axis
122 ! and at ca. 0 at the LCFS
123 bdamp(i) = 2.0_dp*pdamp*(1.0_dp-si)
124 END DO
125
126 ! Avoid round-off
127 sqrts(ns:nrzt:ns) = 1.0_dp ! boundary value
128 shalf(nrzt+1) = 1.0_dp ! no scaling for the weird hidden value at the end of shalf (see ndim in allocate_ns)
129 sqrts(nrzt+1) = 1.0_dp ! no scaling for the weird hidden value at the end of sqrts (see ndim in allocate_ns)
130
131 ! sm, sp used mainly in 1d preconditioner?
132 DO i = 2,ns
133 sm(i) = shalf(i)/sqrts(i)
134 sp(i) = shalf(i+1)/sqrts(i)
135 ENDDO
136
137 sm(1) = 0.0_dp
138 sp(0) = 0.0_dp
139 sp(1) = sm(2)
140
141 if (open_dbg_context("profil1d", num_eqsolve_retries)) then
142
143 call add_real("torflux_edge", torflux_edge)
144 call add_real("polflux_edge", polflux_edge)
145 call add_real("r00", r00)
146 call add_real("lamscale", lamscale)
147 call add_real("currv", currv)
148 call add_real("Itor", itor)
149
150 call add_real_1d("shalf", ns+1, shalf(:ns+1))
151 call add_real_1d("phips", ns, phips(2:ns+1))
152 call add_real_1d("chips", ns-1, chips(2:ns))
153 call add_real_1d("iotas", ns-1, iotas(2:ns))
154 call add_real_1d("icurv", ns-1, icurv(2:ns))
155 call add_real_1d("mass", ns-1, mass(2:ns))
156
157 call add_real_1d("sqrts", ns, sqrts(:ns))
158 call add_real_1d("phipf", ns, phipf)
159 call add_real_1d("chipf", ns, chipf)
160 call add_real_1d("iotaf", ns, iotaf)
161 call add_real_1d("bdamp", ns, bdamp)
162
163 call add_real_1d("sm", ns, sm)
164 call add_real_1d("sp", ns+1, sp)
165
166 call close_dbg_out()
167 end if
168
169END SUBROUTINE profil1d
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 sqrts
sqrt(s), two-dimensional array on full-grid
Definition realspace.f90:32
real(rprec), dimension(:), allocatable shalf
sqrt(s) ,two-dimensional array on half-grid
Definition realspace.f90:31
real(rprec), dimension(:), allocatable sp
shalf(i+1)/sfull(i)
Definition vmec_main.f90:26
real(rprec) hs
radial mesh size increment
Definition vmec_main.f90:84
real(rprec), dimension(:), allocatable chips
poloidal flux (same as chip), one-dimensional array
Definition vmec_main.f90:67
real(rprec), dimension(:), allocatable bdamp
radial mesh-blending factor
Definition vmec_main.f90:27
real(rprec), dimension(:), allocatable sm
shalf(i)/sfull(i)
Definition vmec_main.f90:25
real(rprec) r00
Definition vmec_main.f90:89
real(rprec), dimension(:), allocatable iotaf
rotational transform (full grid)
Definition vmec_main.f90:34
real(rprec), dimension(:), allocatable pres
pressure profile
Definition vmec_main.f90:55
real(rprec), dimension(:), allocatable chipf
radial derivative of poloidal magnetic flux (full grid)
Definition vmec_main.f90:36
real(rprec), dimension(:,:,:), allocatable, target rmn_bdy
integer num_eqsolve_retries
real(rprec) currv
toroidal current (?)
Definition vmec_main.f90:85
real(rprec), dimension(:), allocatable phips
toroidal flux (same as phip), one-dimensional array
Definition vmec_main.f90:68
real(rprec), dimension(:), allocatable mass
mass profile on half-grid
Definition vmec_main.f90:71
logical lflip
from init_geometry
real(rprec), dimension(:), allocatable iotas
rotational transform , on half radial mesh
Definition vmec_main.f90:69
real(rprec), dimension(:), allocatable phipf
radial derivative of toroidal magnetic flux (full grid)
Definition vmec_main.f90:35
real(rprec), dimension(:), allocatable icurv
(-)toroidal current inside flux surface (vanishes like s)
Definition vmec_main.f90:70
real(rprec) signgs
sign of Jacobian : must be =1 (right-handed) or =-1 (left-handed)
real(rprec), parameter pdamp
real(rprec) lamscale
subroutine profil1d()
Compute phip and iota profiles on full grid.
Definition profil1d.f90:10