VMEC 8.52
3D Equilibrium solver with nested flux surfaces.
Loading...
Searching...
No Matches
profile_functions.f
Go to the documentation of this file.
1
3
4! File profile_functions.f contains
5! FUNCTION pcurr
6! FUNCTION piota
7! FUNCTION pmass
8! (JDH 2010-03-30)
9!******************************************************************************
10
11 FUNCTION pcurr (xx)
12! Function to compute the current profile
13
14! Variables declared in vmec_input:
15! ac array (0:20) of coefficients
16! ac_aux_s Auxiliary array s, s-values used for splines
17! ac_aux_f Auxiliary array f, function-values used for splines
18! bloat used to expand the current profile
19! pcurr_type character, specifies the parameterization of the profile
20! | - X for parametrization of I-prime(s), _ for I(s)
21! gauss_trunc X Truncated Gaussian - I-prime
22! two_power X Two powers - ac(0) * (1 - s ** ac(1)) ** ac(2)
23! two_power_gs X Two powers with gaussian peaks -
24! ac(0) * ((1 - s ** ac(1)) ** ac(2))*(1 + Sum[ac(i)*Exp(-(s - ac(i+1))/ac(i+2)) ** 2])
25! sum_atan _ sum of arctangents
26! power_series_I _ Power series for I(s) (NOT default)
27! Akima_spline_Ip X Akima spline for I-prime(s)
28! Akima_spline_I _ Akima spline for I(s)
29! cubic_spline_Ip X cubic spline for I-prime(s)
30! cubic_spline_I _ cubic spline for I(s)
31! pedestal _ Pedestal profile
32! rational _ Rational function (ratio of polynomials)
33! line_segment_Ip X Line segments for I-prime(s)
34! line_segment_I _ Line segments for I(s)
35! power_series X Power Series for I-prime(s) (Default)
36
37! Local Variables
38! i integer counter
39! ioff offset for ac array. Should be zero
40! iflag error flag for spline call
41! xx real argument
42! x constrained to be between 0 and 1
43! xp variable for Gauss_legendre quadrature
44! pcurr_type_lc character, pcurr_type -> lower case
45! gli index for Gauss-Legendre quadrature loop
46! gln order of Gauss-Legendre quadrature
47! glx array of abscissa values for Gauss-Legendre quadrature
48! glw array of wieghts for Gauss-Legendre quadrature
49
50! Note that the profile that is parameterized is often I-prime, whereas
51! I(x) (= Integral_from_0_to_x I-prime(s) ds) is the function that pcurr
52! returns. For the default case of a power series, the integral can be
53! computed analytically. For other cases, a numerical quadrature is done,
54! using a 10-point Gauss-Legendre quadrature.
55 USE stel_kinds
56 USE stel_constants, ONLY: zero, one, pi
58 USE line_segment
59 USE functions
60 IMPLICIT NONE
61! ac assumed to be dimensioned (0:n), with n >= 20
62!-----------------------------------------------
63 INTEGER :: i, ioff, iflag
64 REAL(rprec) :: xx, pcurr, x, xp, temp_num, temp_denom
65 CHARACTER(len=20) :: pcurr_type_lc
66
67 ! knots and weights for 10-point Gauss-Legendre quadrature
68 INTEGER, PARAMETER :: gln = 10
69 INTEGER :: gli
70 REAL(rprec), DIMENSION(gln), PARAMETER :: glx = (/
71 & 0.01304673574141414_rprec,
72 & 0.06746831665550774_rprec,
73 & 0.1602952158504878_rprec,
74 & 0.2833023029353764_rprec,
75 & 0.4255628305091844_rprec,
76 & 0.5744371694908156_rprec,
77 & 0.7166976970646236_rprec,
78 & 0.8397047841495122_rprec,
79 & 0.9325316833444923_rprec,
80 & 0.9869532642585859_rprec /)
81 REAL(rprec), DIMENSION(gln), PARAMETER :: glw = (/
82 & 0.03333567215434407_rprec,
83 & 0.0747256745752903_rprec,
84 & 0.1095431812579910_rprec,
85 & 0.1346333596549982_rprec,
86 & 0.1477621123573764_rprec,
87 & 0.1477621123573764_rprec,
88 & 0.1346333596549982_rprec,
89 & 0.1095431812579910_rprec,
90 & 0.0747256745752903_rprec,
91 & 0.03333567215434407_rprec /)
92
93 REAL(rprec) :: g1,g2,g3,g4,a8,a12
94
95!-----------------------------------------------
96!
97! NOTE: AC COEFFICIENTS OBTAINED IN THREED1 FILE
98! BY MATCHING TO <JTOR> * dV/dPHI ~ SUM[x^(i+1) * ac(i)/(i+1)], i=0...UBOUND(ac)
99!
100! Start of executable code
101
102 ! limit radial location to 1, even if bloat factor expands profile further
103 x = min(abs(xx * bloat), one)
104 ioff = lbound(ac,1) ! Expected to be zero.
105
106 pcurr = 0.0_dp
107
108! Convert to Lower Case, to avoid typo issues
109 pcurr_type_lc = pcurr_type
110 CALL tolower(pcurr_type_lc)
111 SELECT CASE(trim(pcurr_type_lc))
112
113 CASE ('gauss_trunc')
114! Truncated Gaussian
115! I-prime(s) = ac(0) * (exp(-(s/ac(1))**2) - exp(-(1/ac(1))**2)
116! Gauss-Legendre Quadrature to get I(s)
117 DO gli = 1,gln
118 xp = x * glx(gli)
119 pcurr = pcurr + glw(gli) * ac(0) *
120 & (exp(-(xp / ac(1)) ** 2.0_dp)
121 & - exp(-( 1.0_dp / ac(1)) ** 2.0_dp))
122 END DO
123 pcurr = pcurr * x ! correct for x interval
124
125 CASE ('two_power')
126! Two power profile
127! I-prime(s) = [1 - s**ac(0)]**ac(1) !! Old as of 2010-05-26
128! I-prime(s) = ac(0) * [1 - s**ac(1)]**ac(2) !! Current as of 2010-05-26
129! Gauss-Legendre Quadrature to get I(s)
130 !DO gli = 1,gln
131 ! xp = x * glx(gli)
132 ! pcurr = pcurr + glw(gli) * two_power(xp, ac)
133 !END DO
134 !pcurr = pcurr * x ! correct for x interval
135 DO gli = 1,gln
136 xp = x * glx(gli)
137 pcurr = pcurr + glw(gli) * ac(0) *
138 & ((1.0_dp-xp**ac(1))**ac(2))
139 END DO
140 pcurr = pcurr * x ! correct for x interval
141
142! CASE ('two_power_gs')
143!! Two power with Gaussian peak profile
144!! I-prime(s) = ac(0) * [1 - s**ac(1)]**ac(2) * (1 + Sum[ac(i)*Exp(-(s - ac(i+1))/ac(i+2)) ** 2])
145!! Gauss-Legendre Quadrature to get I(s)
146! DO gli = 1,gln
147! xp = x * glx(gli)
148! pcurr = pcurr + glw(gli) * two_power_gs(xp, ac)
149! END DO
150! pcurr = pcurr * x ! correct for x interval
151
152 CASE('sum_atan')
153! I(s) - not I-prime(s)
154! pcurr = ac(0) + &
155! & ac(1) * (2/pi) * atan(ac(2)*x**ac(3)/(1-x)**ac(4)) + &
156! & ac(5) * (2/pi) * atan(ac(6)*x**ac(7)/(1-x)**ac(8)) + &
157! & ac(9) * (2/pi) * atan(ac(10)*x**ac(11)/(1-x)**ac(12)) + &
158! & ac(13) * (2/pi) * atan(ac(14)*x**ac(15)/(1-x)**ac(16)) + &
159! & ac(17) * (2/pi) * atan(ac(18)*x**ac(19)/(1-x)**ac(20))
160 IF (x .ge. one) THEN
161 pcurr = ac(0) + ac(1) + ac(5) + ac(9) + ac(13) + ac(17)
162 ELSE
163 pcurr = ac(0) + (2.0_dp/pi) * &
164 & (ac(1) * atan(ac(2)*x**ac(3)/(1-x)**ac(4)) + &
165 & ac(5) * atan(ac(6)*x**ac(7)/(1-x)**ac(8)) + &
166 & ac(9) * atan(ac(10)*x**ac(11)/(1-x)**ac(12)) + &
167 & ac(13) * atan(ac(14)*x**ac(15)/(1-x)**ac(16)) + &
168 & ac(17) * atan(ac(18)*x**ac(19)/(1-x)**ac(20)))
169 ENDIF
170
171 CASE('power_series_I','power_series_i') ! former ipcurr=3
172! I(s) - not I-prime(s)
173! I(s) = Sum(i,0,-)[ac(i) * s ** (i + 1)]
174! Note that coefficient interpretation here is different from other
175! polynomial parameterizations, where the terms are a_(i) * s ** i
176! Note that I(0) = 0.
177 DO i = ubound(ac,1), ioff, -1
178 pcurr = (pcurr + ac(i))*x
179 END DO
180
181 CASE('Akima_spline_I','akima_spline_i') ! former ipcurr=11
182! I(s) with Akima splines
183! Akima-spline for current profile
184! i = minloc(scugrid(2:ndatafmax),dim=1) ! this is where zeros are again
185 i = minloc(ac_aux_s(2:),dim=1) ! this is where zeros are again
186 IF (i < 4) stop 'pcurr: check s-grid for curr-grid values!'
187! call spline_akima(x,pcurr,scugrid,cugrid,i,iflag)
188 CALL spline_akima(x,pcurr,ac_aux_s,ac_aux_f,i,iflag)
189 IF(iflag < 0) &
190 & stop 'pcurr: outside value from spline_akima requested'
191
192 CASE('Akima_spline_Ip','akima_spline_ip') ! former ipcurr=12
193! I(s) from I-prime(s)-values
194! uses an integrated Akima-spline to deliver the values of the toroidal current
195! i = minloc(scdgrid(2:ndatafmax),dim=1) ! this is where zeros are again
196 i = minloc(ac_aux_s(2:),dim=1) ! this is where zeros are again
197 IF(i < 4)stop 'pcurr: check s-grid for curr.dens.-grid values!'
198! call spline_akima_int(x,pcurr,scdgrid,cdgrid,i,iflag)
200 IF (iflag < 0) THEN
201 WRITE(6,*)"x = ", x
202 stop 'pcurr: outside value from spline_akima_int requested'
203 ENDIF
204! Note that spline_akima_int integrates with ac_aux_s(1) as the lower limit.
205! Assumption here is that lower limit is s = 0. Check this assumption.
206 IF (abs(ac_aux_s(1)) .gt. 0.0001_dp) THEN
207 WRITE(*,*) ' Error in profile_functions, Akima_spline_Ip'
208 WRITE(*,*) .gt.' ABS(ac_aux_s(1)) 0.0001'
209 WRITE(*,*) ' Fix This. Stopping'
210 stop
211 ENDIF
212
213 CASE('cubic_spline_I','cubic_spline_i') ! former ipcurr=13
214! I(s) with Cubic splines
215! Cubic-spline for current profile
216! i = minloc(scugrid(2:ndatafmax),dim=1) ! this is where zeros are again
217 i = minloc(ac_aux_s(2:),dim=1) ! this is where zeros are again
218 IF(i < 4) stop 'pcurr: check s-grid for curr-grid values!'
219! call spline_cubic(x,pcurr,scugrid,cugrid,i,iflag)
220 CALL spline_cubic(x,pcurr,ac_aux_s,ac_aux_f,i,iflag)
221 IF (iflag < 0) THEN
222 IF(iflag == -1) THEN
223 stop'pcurr: outside value from spline_cubic requested'
224 ELSEIF(iflag == -2) THEN
225 stop 'pcurr: identical scugrid-values in spline_cubic'
226 ELSE
227 stop 'pcurr: unknown error from spline_cubic'
228 ENDIF
229 ENDIF
230
231 CASE('cubic_spline_Ip','cubic_spline_ip') ! former ipcurr=14
232! I(s) from I-prime(s)-values
233! uses an integrated Cubic-spline to deliver the values of the toroidal current
234! i = minloc(scdgrid(2:ndatafmax),dim=1) ! this is where zeros are again
235 i = minloc(ac_aux_s(2:),dim=1) ! this is where zeros are again
236 IF(i < 4) stop 'pcurr: check s-grid for curr.dens.-grid values!'
237! call spline_cubic_int(x,pcurr,scdgrid,cdgrid,i,iflag)
239 IF (iflag < 0)THEN
240 IF (iflag == -1) THEN
241 stop'pcurr: outside value from spline_cubic_int requested'
242 ELSEIF (iflag == -2) THEN
243 stop 'pcurr: identical scdgrid-values in spline_cubic_int'
244 ELSE
245 stop 'pcurr: unknown error from spline_cubic_int'
246 ENDIF
247 ENDIF
248! Note that spline_cubic_int integrates with ac_aux_s(1) as the lower limit.
249! Assumption here is that lower limit is s = 0. Check this assumption.
250 IF (abs(ac_aux_s(1)) .gt. 0.0001_dp) THEN
251 WRITE(*,*) ' Error in profile_functions, cubic_spline_Ip'
252 WRITE(*,*) .gt.' ABS(ac_aux_s(1)) 0.0001'
253 WRITE(*,*) ' Fix This. Stopping'
254 stop
255 ENDIF
256
257 CASE ('pedestal')
258! Parameterization for I(s)
259! Added by SPH 2010-05-26
260 DO i = 7, ioff, -1
261 pcurr = x*pcurr + ac(i)/(i-ioff+1.0_dp)
262 END DO
263 pcurr = x*pcurr
264
265 i=8
266 IF (ac(i+3) .le. 0._dp ) THEN
267 ac(i:i+4) = 0.0_dp
268 ac(i+3) = 1.0e30_dp
269 ELSE
270 ac(i+4) = 1.0_dp/
271 1 (tanh(2.0_dp*ac(i+2)/ac(i+3))-
272 2 tanh(2.0_dp*(ac(i+2)-1)/ac(i+3)))
273 END IF
274
275 a8 =max(ac(i+8),0.01_dp)
276 a12=max(ac(i+12),0.01_dp)
277
278 g1= (x-ac(i+7))/a8
279 g3= (-ac(i+7))/a8
280 g2= (x-ac(i+11))/a12
281 g4= (-ac(i+11))/a12
282 pcurr = pcurr + ac(i+4) * ac(i+0) *
283 1 ( tanh( 2.0_dp*ac(i+2)/ac(i+3) )
284 2 -tanh( 2.0_dp*(ac(i+2)-sqrt(x))/ac(i+3) ) )
285 3 +ac(i+5)*( tanh(g1) - tanh(g3) )
286 4 +ac(i+9)*( tanh(g2) - tanh(g4) )
287
288
289 CASE('rational') !
290! I(s) - not I-prime(s). No need for Gaussian quadrature.
291! Ratio of polynomials.
292! Numerator coefficients: ac(LBOUND) - ac(9)
293! Denominator coefficients: ac(10) - ac(UBOUND(ac,1))
294 temp_num = zero
295 temp_denom = zero
296 DO i = 9, ioff, -1
297 temp_num = x * temp_num + ac(i)
298 END DO
299 DO i = ubound(ac,1), 10, -1
300 temp_denom = x * temp_denom + ac(i)
301 END DO
302 IF (temp_denom .ne. zero) THEN
303 pcurr = temp_num / temp_denom
304 ELSE
305 pcurr = huge(pcurr)
306 ENDIF
307
308 CASE('line_segment_Ip', 'line_segment_ip')
309!! I(s) from I-prime(s)-values. Integrated line segments to determine the plasma
310!! current.
311 i = minloc(ac_aux_s(2:),dim=1)
313
314 CASE('line_segment_I', 'line_segment_i')
315!! I(s) values. Linearly interpolated line segments to determine the plasma
316!! current.
317 i = minloc(ac_aux_s(2:),dim=1)
319
320 CASE DEFAULT
321! Power series
322! I-prime(s) = Sum(i,0,-)[ac(i) * s ** i]
323! Analytic integration to get I(s)
324 DO i = ubound(ac,1), ioff, -1
325 pcurr = x*pcurr + ac(i)/(i-ioff+1.0_dp)
326 END DO
327 IF (trim(pcurr_type_lc) .ne. 'power_series') THEN
328 WRITE(*,*) 'Unrecognized pcurr_type:', pcurr_type
329 WRITE(*,*) ' *** CHECK YOUR INPUT ***'
330 WRITE(*,*) 'Changing pcurr_type from ''', &
331 & trim(pcurr_type), '''to ''power_series''.'
332 pcurr_type = 'power_series'
333 END IF
334 pcurr = x*pcurr
335 END SELECT
336
337 END FUNCTION pcurr
338
339!******************************************************************************
340
341 FUNCTION piota (x)
342! Function to compute the iota/q profile.
343
344! Variables declared in vmec_input:
345! ai array (0:20) of coefficients
346! ai_aux_s Auxiliary array s, s-values used for splines
347! ai_aux_f Auxiliary array f, function-values used for splines
348! piota_type character, specifies the parameterization of the profile
349! sum_atan Sum of atan functions plus offset.
350! Akima_spline Akima spline
351! cubic_spline cubic spline
352! rational rational (ratio of polynomials)
353! nice_quadratic quadratic with rerranged coefficients.
354! line_segment Linearly interpolated line segments
355! power_series Power Series (Default)
356
357! Local Variables
358! i integer counter
359! iflag error flag for spline call
360! x real argument
361! x constrained to be between 0 and 1
362! piota_type_lc character, piota_type -> lower case
363
364 USE stel_kinds
365 USE stel_constants, ONLY: zero, one, pi
367 USE line_segment
368 IMPLICIT NONE
369! ai assumed to be dimensioned (0:n), with n >= 20
370!-----------------------------------------------
371 INTEGER :: i, iflag, ioff
372 REAL(rprec) :: x, piota, temp_num, temp_denom
373 CHARACTER(len=20) :: piota_type_lc
374!-----------------------------------------------
375 piota = 0.0_dp
376 ioff = lbound(ai,1) ! Expected to be zero.
377
378! Convert to Lower Case, to avoid typo issues
379 piota_type_lc = piota_type
380 CALL tolower(piota_type_lc)
381 SELECT CASE(trim(piota_type_lc))
382
383 CASE('sum_atan')
384! Sum atan functions mapped to [0:1], with an ai(0) offset
385! piota = ai(0) + &
386! & ai(1) * (2/pi) * atan(ai(2)*x**ai(3)/(1-x)**ai(4)) + &
387! & ai(5) * (2/pi) * atan(ai(6)*x**ai(7)/(1-x)**ai(8)) + &
388! & ai(9) * (2/pi) * atan(ai(10)*x**ai(11)/(1-x)**ai(12)) + &
389! & ai(13) * (2/pi) * atan(ai(14)*x**ai(15)/(1-x)**ai(16)) + &
390! & ai(17) * (2/pi) * atan(ai(18)*x**ai(19)/(1-x)**ai(20))
391 IF (x .ge. one) THEN
392 piota = ai(0) + ai(1) + ai(5) + ai(9) + ai(13) + ai(17)
393 ELSE
394 piota = ai(0) + (2.0_dp/pi) * &
395 & (ai(1) * atan(ai(2)*x**ai(3)/(1-x)**ai(4)) + &
396 & ai(5) * atan(ai(6)*x**ai(7)/(1-x)**ai(8)) + &
397 & ai(9) * atan(ai(10)*x**ai(11)/(1-x)**ai(12)) + &
398 & ai(13) * atan(ai(14)*x**ai(15)/(1-x)**ai(16)) + &
399 & ai(17) * atan(ai(18)*x**ai(19)/(1-x)**ai(20)))
400 ENDIF
401
402 CASE('Akima_spline','akima_spline') ! former ipiota=11
403! Akima-spline (iogrid + siogrid)
404! i = minloc(siogrid(2:ndatafmax),dim=1) ! this is where zeros are again
405 i = minloc(ai_aux_s(2:),dim=1) ! this is where zeros are again
406 if(i < 4) stop 'piota: check s-grid for iota-grid values!'
407! call spline_akima(x,piota,siogrid,iogrid,i,iflag)
408 call spline_akima(x,piota,ai_aux_s,ai_aux_f,i,iflag)
409 if(iflag < 0) &
410 & stop'piota: outside value from spline_akima requested'
411
412 CASE('cubic_spline') ! former ipiota=13
413! cubic-spline (iogrid + siogrid)
414! i = minloc(siogrid(2:ndatafmax),dim=1) ! this is where zeros are again
415 i = minloc(ai_aux_s(2:),dim=1) ! this is where zeros are again
416 if(i < 4) stop 'piota: check s-grid for iota-grid values!'
417! call spline_cubic(x,piota,siogrid,iogrid,i,iflag)
418 call spline_cubic(x,piota,ai_aux_s,ai_aux_f,i,iflag)
419 if(iflag < 0)then
420 if(iflag == -1) then
421 stop'piota: outside value from spline_cubic requested'
422 elseif(iflag == -2) then
423 stop'piota: identical siogrid-values in spline_cubic'
424 else
425 stop 'piota: unknown error from spline_cubic'
426 endif
427 endif
428
429 CASE('rational') !
430! Ratio of polynomials.
431! Numerator coefficients: ai(LBOUND) - ai(9)
432! Denominator coefficients: ai(10) - ai(UBOUND)
433 temp_num = zero
434 temp_denom = zero
435 DO i = 9, ioff, -1
436 temp_num = x * temp_num + ai(i)
437 END DO
438 DO i = ubound(ai,1), 10, -1
439 temp_denom = x * temp_denom + ai(i)
440 END DO
441 IF (temp_denom .ne. zero) THEN
442 piota = temp_num / temp_denom
443 ELSE
444 piota = huge(piota)
445 ENDIF
446
447 CASE('nice_quadratic') !
448! Quadratic with slightly rearranged coefficients.
449! iota(s) = a0(1-s) + a1 s + 4 a2 s (1 - s)
450! a0 is the iota value at s = 0
451! a1 is the iota value at s = 1
452! a2 is the shift of iota(1/2) from the straight line value
453! (Thus, a2 = 0 gives a linear iota profile.
454 piota = ai(0) * (one - x) + ai(1) * x + 4 * ai(2) * &
455 & x * (one - x)
456
457 CASE('line_segment')
458!! Linearly interpolated line segments to determine the iotabar profile.
459 i = minloc(ai_aux_s(2:),dim=1)
461
462 CASE default
463! Power Series is the default
464 DO i = ubound(ai,1), lbound(ai,1), -1
465 piota = x*piota + ai(i)
466 END DO
467 IF (trim(piota_type_lc) .ne. 'power_series') THEN
468 WRITE(*,*) 'Unrecognized piota_type:', piota_type
469 WRITE(*,*) ' *** CHECK YOUR INPUT ***'
470 WRITE(*,*) 'Changing piota_type from ''', &
471 & trim(piota_type), '''to ''power_series''.'
472 piota_type = 'power_series'
473 END IF
474 END SELECT
475
476 END FUNCTION piota
477
478!******************************************************************************
479
480 FUNCTION pmass (xx)
481! Function to compute the mass (pressure) profile
482
483! Variables declared in vmec_input:
484! am array (0:20) of coefficients
485! am_aux_s Auxiliary array s, s-values used for splines
486! am_aux_f Auxiliary array f, function-values used for splines
487! bloat used to expand the profile
488! pmass_type character, specifies the parameterization of the profile
489! gauss_trunc Truncated Gaussian
490! two_power am(0) * [1 - s**am(1)]**am(2)
491! two_power_gs am(0) * [1 - s**am(1)]**am(2)*
492! (1 + Sum[am(i)*Exp(-((x - am(i+1))/am(i+2))**2)])
493! two_Lorentz two Lorentz-type functions, mapped to [0:1]
494! Akima_spline Akima-spline (magrid[-> am_aux_f] + smagrid[-> am_aux_s])
495! cubic_spline Cubic-spline (magrid[-> am_aux_f] + smagrid[-> am_aux_s])
496! pedestal Pedestal profile
497! rational rational (ratio of polynomials)
498! line_segment Linearly interpolated line segments
499! power_series Power Series (Default)
500
501! Local Variables
502! i integer counter
503! iflag error flag for spline call
504! xx real argument
505! x constrained to be between 0 and 1
506! pmass_type_lc character, pmass_type -> lower case
507
508 USE stel_kinds
509 USE stel_constants, ONLY: zero, one
510 USE vmec_input, ONLY: am, bloat, pres_scale, pmass_type, &
512! am is assumed to be dimensioned starting at zero.
513 USE vparams, ONLY: mu0
514 USE line_segment
515 USE functions
516 IMPLICIT NONE
517!-----------------------------------------------
518 INTEGER :: i, iflag, ioff
519 REAL(rprec) :: xx, pmass, x, temp_num, temp_denom
520 CHARACTER(len=20) :: pmass_type_lc
521!-----------------------------------------------
522! NOTE: On entry, am is in pascals. pmass internal units are mu0*pascals (B**2 units)
523 x = min(abs(xx * bloat), 1._dp)
524
525 pmass = 0.0_dp
526 ioff = lbound(am,1) ! Expected to be zero.
527
528! Convert to Lower Case, to avoid typo issues
529 pmass_type_lc = pmass_type
530 CALL tolower(pmass_type_lc)
531 SELECT CASE(trim(pmass_type_lc))
532
533 CASE ('gauss_trunc')
534! Truncated Gaussian
535! p(s) = am(0) * (exp(-(s/am(1))**2) - exp(-(1/am(1))**2)
536! Above Old as of 2010-05-26
537! Below current as of 2010-05-26
538! p(s) = (am(0) / c) * (exp(-(s/am(1))**2) - exp(-(1/am(1))**2)
539! c = (1 - exp(-(1/am(1))**2) ! so that p(0) = am(0).
540 pmass = (am(0)/(one - exp(-(one / am(1)) ** 2.0_dp))) * &
541 & (exp(-(x / am(1)) ** 2.0_dp) -exp(-(one / am(1)) ** 2.0_dp))
542
543 CASE ('two_power')
544! Two power profile
545! p(s) = [1 - s**am(0)]**am(1) !! Old as of 2010-05-26
546! p(s) = am(0) * [1 - s**am(1)]**am(2) !! Current as of 2010-05-26
547 pmass = am(0) * ((one-x**am(1))**am(2))
548 !pmass = two_power(x, am)
549
550! CASE ('two_power_gs')
551!! Two power profile with guassian peaks.
552! pmass = two_power_gs(x, am)
553
554 CASE ('two_Lorentz','two_lorentz') ! former ipmass=1
555 pmass = am(0)*(am(1)*(one/(one+( x/am(2)**2)**am(3))**am(4) &
556 & -one/(one+(one/am(2)**2)**am(3))**am(4))/ &
557 & (one-one/(one+(one/am(2)**2)**am(3))**am(4))+ &
558 & (one-am(1))*(one/(one+( x/am(5)**2)**am(6))**am(7) &
559 & -one/(one+(one/am(5)**2)**am(6))**am(7))/ &
560 & (one-one/(one+(one/am(5)**2)**am(6))**am(7))) &
561
562 CASE ('Akima_spline','akima_spline') ! former ipmass=11
563! i = minloc(smagrid(2:ndatafmax),dim=1) ! this is where zeros are again
564 i = minloc(am_aux_s(2:),dim=1) ! this is where zeros are again
565 IF(i < 4) stop 'pmass: check s-grid for mass-grid values!'
566! call spline_akima(x,pmass,smagrid,magrid,i,iflag)
567 CALL spline_akima(x,pmass,am_aux_s,am_aux_f,i,iflag)
568 IF(iflag < 0) &
569 & stop 'pmass: outside value from spline_akima requested'
570
571 CASE ('cubic_spline') ! former ipmass=13
572! i = minloc(smagrid(2:ndatafmax),dim=1) ! this is where zeros are again
573 i = minloc(am_aux_s(2:),dim=1) ! this is where zeros are again
574 IF(i < 4) stop 'pmass: check s-grid for mass-grid values!'
575! call spline_cubic(x,pmass,smagrid,magrid,i,iflag)
576 CALL spline_cubic(x,pmass,am_aux_s,am_aux_f,i,iflag)
577 IF (iflag < 0) THEN
578 IF (iflag == -1) THEN
579 stop'pmass: outside value from spline_cubic requested'
580 ELSEIF (iflag == -2) THEN
581! STOP'pmass: identical smagrid-values in spline_cubic'
582 stop'pmass: identical am_aux_s-values in spline_cubic'
583 ELSE
584 stop 'pmass: unknown error from spline_cubic'
585 ENDIF
586 ENDIF
587
588 CASE ('pedestal') !PMV Texas group
589! Added by SPH 2010-05-26
590
591 DO i = 15, lbound(am,1), -1
592 pmass = x*pmass + am(i)
593 END DO
594
595 i = 16
596 IF (am(i+3) .le. 0._dp ) THEN
597 am(i:i+4) = 0.0_dp
598 am(i+3) = 1.0e30_dp
599 ELSE
600 am(i+4) = 1.0_dp/
601 1 (tanh(2.0_dp*am(i+2)/am(i+3))-
602 2 tanh(2.0_dp*(am(i+2)-1)/am(i+3)))
603 END IF
604
605 pmass = pmass + am(i+4) * am(i+1) *
606 1 ( tanh( 2.0_dp*(am(i+2)-sqrt(x))/am(i+3) )
607 2 -tanh( 2.0_dp*(am(i+2)-1._dp) /am(i+3) ) )
608
609 CASE('rational') !
610! Ratio of polynomials.
611! Numerator coefficients: am(LBOUND) - am(9)
612! Denominator coefficients: am(10) - am(UBOUND)
613 temp_num = zero
614 temp_denom = zero
615 DO i = 9, ioff, -1
616 temp_num = x * temp_num + am(i)
617 END DO
618 DO i = ubound(am,1), 10, -1
619 temp_denom = x * temp_denom + am(i)
620 END DO
621 IF (temp_denom .ne. zero) THEN
622 pmass = temp_num / temp_denom
623 ELSE
624 pmass = huge(pmass)
625 ENDIF
626
627 CASE('line_segment')
628!! Linearly interpolated line segments to determine the pressure profile.
629 i = minloc(am_aux_s(2:),dim=1)
631
632 CASE DEFAULT
633 DO i = ubound(am,1), lbound(am,1), -1
634 pmass = x*pmass + am(i)
635 END DO
636 IF (trim(pmass_type_lc) .ne. 'power_series') THEN
637 WRITE(*,*) 'Unrecognized pmass_type:', pmass_type
638 WRITE(*,*) ' *** CHECK YOUR INPUT ***'
639 WRITE(*,*) 'Changing pmass_type from ''', &
640 & trim(pmass_type), '''to ''power_series''.'
641 pmass_type = 'power_series'
642 END IF
643 END SELECT
644
646
647 END FUNCTION pmass
subroutine spline_akima(x, y, xx, yy, npts, iflag)
This module containes code to create a profile constructed of line segments. These line segments are ...
subroutine, public line_seg_int(x, y, xx, yy, n)
subroutine, public line_seg(x, y, xx, yy, n)
real(dp), parameter pi
real(dp), parameter mu0
real(dp), parameter one
real(dp), parameter zero
integer, parameter rprec
real(rprec), dimension(0:20) ac
array of coefficients in phi-series for the quantity d(Icurv)/ds = toroidal current density * Vprime,...
real(rprec) pres_scale
character(len=20) pcurr_type
real(rprec), dimension(ndatafmax) ac_aux_f
real(rprec), dimension(ndatafmax) ai_aux_s
character(len=20) pmass_type
real(rprec), dimension(ndatafmax) am_aux_s
character(len=20) piota_type
real(rprec), dimension(ndatafmax) ai_aux_f
real(rprec), dimension(0:20) am
array of coefficients in phi-series for mass (NWT/m**2)
real(rprec), dimension(ndatafmax) am_aux_f
real(rprec) bloat
real(rprec), dimension(ndatafmax) ac_aux_s
real(rprec), dimension(0:20) ai
array of coefficients in phi-series for iota (ncurr=0)
real(rprec) function piota(x)
real(rprec) function pcurr(xx)
real(rprec) function pmass(xx)
subroutine spline_akima_int(x, y, xx, yy, npts, iflag)
subroutine spline_cubic(x, y, xx, yy, n, iflag)
Definition spline_cubic.f:3
subroutine spline_cubic_int(x, y, xx, yy, n, iflag)
subroutine tolower(string)
Convert a string to lower case.
Definition tolower.f90:10