VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
residue.f90
Go to the documentation of this file.
1
3
9SUBROUTINE residue (gcr, gcz, gcl, fsqrz, old_fsqz)
10
11 USE vmec_main, p5 => cp5
12 USE vmec_params, ONLY: rss, zcs, rsc, zcc, meven, modd, ntmax
13 USE xstuff
14
15 use dbgout
16
17 IMPLICIT NONE
18
19 REAL(rprec), DIMENSION(ns,0:ntor,0:mpol1,ntmax), INTENT(inout) :: gcr
20 REAL(rprec), DIMENSION(ns,0:ntor,0:mpol1,ntmax), INTENT(inout) :: gcz
21 REAL(rprec), DIMENSION(ns,0:ntor,0:mpol1,ntmax), INTENT(inout) :: gcl
22 real(rprec), intent(in) :: fsqrz, old_fsqz
23
24 INTEGER, PARAMETER :: n0=0
25 INTEGER, PARAMETER :: m0=0
26 INTEGER, PARAMETER :: m1=1
27 INTEGER, PARAMETER :: n3d=0
28 INTEGER, PARAMETER :: nasym=1
29
30 INTEGER :: jedge, j, n, m, i
31 INTEGER :: delIter
32 REAL(rprec) :: r1
33 logical, parameter :: skip_scalfor_dbg = .false.
34
35 ! IMPOSE M=1 MODE CONSTRAINT TO MAKE THETA ANGLE
36 ! INVARIANT TO PHI-SHIFTS (AND THETA SHIFTS FOR ASYMMETRIC CASE)
37 ! (ZCS = RSS, ZSS = RCS ARE THE CORRECT POLAR RELATIONS)
38
39! #ifndef _HBANGLE
40 ! SYMMETRIC PERTURBATIONS (BASED ON POLAR RELATIONS):
41 ! RSS(n) = ZCS(n), n != 0
42 ! ASYMMETRIC PERTURBATIONS:
43 ! RSC(n) = ZCC(n), ALL n
44 !
45 ! INTERNALLY:
46 ! XC(rss) = .5*(Rss + Zcs), XC(zcs) = .5*(Rss - Zcs) -> 0
47 ! XC(rsc) = .5*(Rsc + Zcc), XC(zcc) = .5*(Rsc - Zcc) -> 0
48 ! THIS IMPLIES THE CONSTRAINT
49 ! 3D ONLY : GC(zcs) = 0;
50 ! ASYM: GC(zcc) = 0
51 IF (lthreed) CALL constrain_m1(gcr(:,:,m1,rss), gcz(:,:,m1,zcs), old_fsqz)
52 IF (lasym) CALL constrain_m1(gcr(:,:,m1,rsc), gcz(:,:,m1,zcc), old_fsqz)
53! #end /* ndef _HBANGLE */
54
55 ! dump physical forces
56 if (open_dbg_context("phys_gc", num_eqsolve_retries)) then
57
58 call add_real_4d("gcr", ntmax, ns, ntor1, mpol, gcr, order=(/ 2, 3, 4, 1 /) )
59 call add_real_4d("gcz", ntmax, ns, ntor1, mpol, gcz, order=(/ 2, 3, 4, 1 /) )
60 call add_real_4d("gcl", ntmax, ns, ntor1, mpol, gcl, order=(/ 2, 3, 4, 1 /) )
61
62 call close_dbg_out()
63 end if
64
65 ! COMPUTE INVARIANT RESIDUALS
66 r1 = one/(2.0_dp*r0scale)**2.0_dp ! --> actually look at r1*fnorm --> scaling factor for forces (?)
67 jedge = 0
68
69 ! SPH-JAH013108: MUST INCLUDE EDGE FORCE (INITIALLY) FOR V3FITA TO WORK
70 ! ADD A V3FIT RELATED FLAG? ADD fsq criterion first
71 deliter = iter2-iter1
72
73 ! Coding for VMEC2000 run stand-alone
74 IF (deliter.lt.50 .and. fsqrz.lt.1.e-6_dp) then
75 ! include edge contribution only if converged well enough fast enough (?)
76! print *, "include edge force in residue"
77 jedge = 1
78 end if
79
80 CALL getfsq (gcr, gcz, fsqr, fsqz, r1*fnorm, jedge)
81
82 fsql = fnorml*sum(gcl*gcl)
83 fedge = r1*fnorm * sum(gcr(ns,:,:,:)**2.0_dp + gcz(ns,:,:,:)**2.0_dp)
84
86
87 call add_real("r0scale", r0scale) ! TODO: move to debug output of fixaray
88 call add_real("r1", r1)
89 call add_real("fnorm", fnorm)
90 call add_real("fnormL", fnorml)
91 call add_int("jedge", jedge)
92 call add_real("fsqr", fsqr)
93 call add_real("fsqz", fsqz)
94 call add_real("fsql", fsql)
95 call add_real("fedge", fedge)
96
97 call close_dbg_out()
98 end if
99
100 ! PERFORM PRECONDITIONING AND COMPUTE RESIDUES
101
102! #ifndef _HBANGLE
103 ! m = 1 constraint scaling
104 IF (lthreed) CALL scale_m1(gcr(:,:,1,rss), gcz(:,:,1,zcs))
105 IF (lasym) CALL scale_m1(gcr(:,:,1,rsc), gcz(:,:,1,zcc))
106
107 ! dump forces after scale_m1 has been applied
108 if (open_dbg_context("scale_m1", num_eqsolve_retries)) then
109
110 call add_real_4d("gcr", ntmax, ns, ntor1, mpol, gcr, order=(/ 2, 3, 4, 1 /) )
111 call add_real_4d("gcz", ntmax, ns, ntor1, mpol, gcz, order=(/ 2, 3, 4, 1 /) )
112
113 call close_dbg_out()
114 end if
115
116 jedge = 0
117 CALL scalfor (gcr, arm, brm, ard, brd, crd, jedge, skip_scalfor_dbg)
118 jedge = 1
119 CALL scalfor (gcz, azm, bzm, azd, bzd, crd, jedge, skip_scalfor_dbg)
120! #end /* ndef _HBANGLE */
121
122 !SPH: THIS IS NOT INVARIANT UNDER PHIP->A*PHIP, AM->A**2*AM IN PROFIL1D
123 ! (EXTCUR -> A*EXTCUR for FREE BOUNDARY)
124 gcl = faclam*gcl
125
126 ! dump forces after scalfor has been applied
127 if (open_dbg_context("scalfor_out", num_eqsolve_retries)) then
128
129 call add_real_2d("arm", ns+1, 2, arm)
130 call add_real_2d("ard", ns+1, 2, ard)
131 call add_real_2d("brm", ns+1, 2, brm)
132 call add_real_2d("brd", ns+1, 2, brd)
133 call add_real_1d("crd", ns+1, crd)
134 call add_real_2d("azm", ns+1, 2, azm)
135 call add_real_2d("azd", ns+1, 2, azd)
136 call add_real_2d("bzm", ns+1, 2, bzm)
137 call add_real_2d("bzd", ns+1, 2, bzd)
138
139 call add_real_4d("gcr", ntmax, ns, ntor1, mpol, gcr, order=(/ 2, 3, 4, 1 /) )
140 call add_real_4d("gcz", ntmax, ns, ntor1, mpol, gcz, order=(/ 2, 3, 4, 1 /) )
141 call add_real_4d("gcl", ntmax, ns, ntor1, mpol, gcl, order=(/ 2, 3, 4, 1 /) )
142
143 call close_dbg_out()
144 end if
145
146 !SPH: add fnorm1 ~ 1/R**2, since preconditioned forces gcr,gcz ~ Rmn or Zmn
147 CALL getfsq (gcr, gcz, fsqr1, fsqz1, fnorm1, m1) ! m1 is simply == 1 --> include edge
148 fsql1 = hs*sum(gcl*gcl)
149 !030514 fsql1 = hs*lamscale**2*SUM(gcl*gcl)
150
151 if (open_dbg_context("fsq1", num_eqsolve_retries)) then
152
153 call add_real("fnorm1", fnorm1)
154 call add_real("fsqr1", fsqr1)
155 call add_real("fsqz1", fsqz1)
156 call add_real("fsql1", fsql1)
157
158 call close_dbg_out()
159 end if
160
161END SUBROUTINE residue
162
167SUBROUTINE constrain_m1(gcr, gcz, old_fsqz)
168
169 USE vmec_main, p5 => cp5
170
171 IMPLICIT NONE
172
173 REAL(dp), DIMENSION(ns,0:ntor), INTENT(inout) :: gcr, gcz
174 real(dp), intent(in) :: old_fsqz
175
176 REAL(dp), PARAMETER :: FThreshold = 1.e-6_dp
177 REAL(dp) :: temp(ns,0:ntor)
178
179 ! COMPUTE INTERNAL gr, gz
180 ! NOTE: internal gz => 0 for both values of lconm1 (although gz is different)
181 ! FOR lconm1=T, gcr(internal) = gcr+gcz, gcz(internal) = gcr-gcz->0
182 IF (lconm1) THEN
183 temp = gcr
184 gcr = osqrt2*(gcr + gcz)
185 gcz = osqrt2*(temp - gcz)
186 END IF
187
188 !v8.50: ADD iter2<2 so reset=<WOUT_FILE> works
189 IF (old_fsqz.LT.fthreshold .OR. iter2.LT.2) then
190 !write(*,*) "zero z-force in constrain_m1"
191
192 ! ensure that the m=1 constraint is satisfied exactly
193 ! --> the corresponding m=1 coeffs of R,Z are constrained to be zero
194 ! and thus must not be "forced" (by the time evol using gc) away from zero
195 gcz = 0.0_dp
196 end if
197
198END SUBROUTINE constrain_m1
199
204SUBROUTINE scale_m1(gcr, gcz)
205
206 USE vmec_main
207
208 IMPLICIT NONE
209
210 REAL(rprec), DIMENSION(ns,0:ntor), INTENT(inout) :: gcr, gcz
211
212 INTEGER, PARAMETER :: nodd=2
213 INTEGER :: n
214 REAL(rprec) :: fac(ns)
215
216 IF (lconm1) then
217
218 fac = (ard(:ns,nodd)+brd(:ns,nodd) ) &
219 /(ard(:ns,nodd)+brd(:ns,nodd)+azd(:ns,nodd)+bzd(:ns,nodd))
220 DO n = 0, ntor
221 gcr(:,n) = fac*gcr(:,n)
222 END DO
223
224 fac = ( azd(:ns,nodd)+bzd(:ns,nodd)) &
225 /(ard(:ns,nodd)+brd(:ns,nodd)+azd(:ns,nodd)+bzd(:ns,nodd))
226 DO n = 0, ntor
227 gcz(:,n) = fac*gcz(:,n)
228 END DO
229
230 end if
231
232END SUBROUTINE scale_m1
subroutine getfsq(gcr, gcz, gnormr, gnormz, gnorm, medge)
Compute total force residual on flux surfaces.
Definition getfsq.f90:13
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 crd
Definition vmec_main.f90:24
real(rprec) fsqz1
real(rprec) fsql
Definition vmec_main.f90:96
real(rprec), dimension(:,:), allocatable brd
Definition vmec_main.f90:18
real(rprec) hs
radial mesh size increment
Definition vmec_main.f90:84
real(rprec), dimension(:,:), allocatable azd
Definition vmec_main.f90:20
real(rprec), dimension(:,:,:,:), allocatable faclam
Definition vmec_main.f90:28
integer iter1
number of iterations at which the currently active evolution was branched off from
real(rprec) fsqr
Definition vmec_main.f90:94
real(rprec) fsqz
Definition vmec_main.f90:95
real(rprec) fnorm
Definition vmec_main.f90:93
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
logical lconm1
real(rprec), dimension(:,:), allocatable ard
Definition vmec_main.f90:16
real(rprec) fsqr1
Definition vmec_main.f90:99
integer num_eqsolve_retries
real(rprec) fnorm1
Definition vmec_main.f90:97
real(rprec) fedge
real(rprec), dimension(:,:), allocatable arm
Definition vmec_main.f90:17
logical lthreed
real(rprec) r0scale
Definition vmec_main.f90:90
real(rprec) fsql1
integer iter2
total number of iterations
real(rprec), dimension(:,:), allocatable azm
Definition vmec_main.f90:21
integer, parameter modd
parity selection label for odd poloidal modes of R and Z
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
subroutine residue(gcr, gcz, gcl, fsqrz, old_fsqz)
Compute invariant residuals.
Definition residue.f90:10
subroutine constrain_m1(gcr, gcz, old_fsqz)
Compute internal gr , gz required for constraint.
Definition residue.f90:168
subroutine scale_m1(gcr, gcz)
Compute internal gr , gz required for constraint.
Definition residue.f90:205
subroutine scalfor(gcx, axm, bxm, axd, bxd, cx, iflag, skip_scalfor_dbg)
Build forces from different contributions.
Definition scalfor.f90:16