ETS  \$Id: Doxyfile 2162 2020-02-26 14:16:09Z g2dpc $
 All Classes Files Functions Variables Pages
helena21_mod.f90
Go to the documentation of this file.
1 module helena_grid
2  use itm_types
3  implicit none
4  integer :: nr, np
5  real (r8),pointer :: RR(:,:), ZZ(:,:), PSI(:,:)
6  real (r8) :: R_min, R_max, Z_min, Z_max
7 endmodule helena_grid
8 
10  use itm_types
11  implicit none
12  integer :: mf, n_bnd
13  real (r8), allocatable :: fr(:), R_bnd(:), Z_bnd(:)
14  real (r8) :: Bgeo, Rgeo, Zgeo, amin, eps, ellip, tria_u, tria_l, quad_u, quad_l
15  real (r8) :: Reast, Rwest
16 end module helena_boundary
17 
19  use itm_types
20  implicit none
21  integer :: n_prof
22  real (r8),allocatable :: dp_dpsi(:),fdf_dpsi(:),p_psi(:),f_psi(:),zjz_psi(:),q(:)
23  real (r8) :: p_bnd
24 endmodule helena_profiles
25 
27  use itm_types
28  implicit none
29  integer :: n_elms, n_nodes
30  integer,allocatable :: elm_list(:,:), index_list(:), index_inverse(:)
31  real (r8) :: RS(4,2)
32  integer :: IJ(4,2)
33  real (r8) :: H(4,4,4,4), HS(4,4,4,4), HR(4,4,4,4)
34  real (r8) :: HRS(4,4,4,4), HRR(4,4,4,4), HSS(4,4,4,4)
35 end module helena_elements
36 
38  use itm_types
39  implicit none
40  integer :: lda, n_matrix, n_diag
41  real (r8),allocatable :: AA(:,:), BB(:)
42 end module helena_matrix
43 
45  use itm_types
46  implicit none
47  real (r8) :: R_axis, Z_axis, ps_axis, r_ax, s_ax
48  real (r8) :: q_axis, B_axis, CRR_axis, CZZ_axis
49  integer :: ielm_ax
50 end module helena_axis
51 
52 module helena_map
53  use itm_types
54  implicit none
55  integer :: n_psi_map, n_chi_map
56  real (r8), allocatable :: gem11(:,:), gem12(:,:), gem22(:,:), gem33(:,:)
57  real (r8), allocatable :: q_map(:), dq_map(:), p_map(:), dp_map(:), f_map(:), df_map(:)
58  real (r8), allocatable :: RR_map(:,:),ZZ_map(:,:)
59 end module helena_map
60 
62  use itm_types
63  implicit none
64  integer :: n_pieces_max
65  parameter(n_pieces_max = 1000)
66 
68  integer :: n_pieces
69  integer :: elm(n_pieces_max)
70  real (r8) :: r(4,n_pieces_max), s(4,n_pieces_max) ! 4 variables per line piece of the flux surface
71  endtype
72 
73  integer :: n_psi
74  real (r8) ,allocatable :: psi_values(:)
75  type (type_surface), allocatable :: flux_surfaces(:)
76 
77 end module helena_surfaces
78 
80  use itm_types
81  implicit none
82  real (r8) :: beta_p, beta_t, beta_n, current, volume, area
83 end module helena_phys
84 
86  use itm_types
87  implicit none
88  real (r8) :: xgauss(4),wgauss(4)
89  data xgauss /-0.861136311594053, -0.339981043584856, 0.339981043584856, 0.861136311594053 /
90  data wgauss / 0.347854845137454, 0.652145154862546, 0.652145154862546, 0.347854845137454 /
91 end module helena_gauss_4
92 
94  use itm_types
95  implicit none
96  real (r8) :: PI, MU_zero
97  parameter( pi = 3.14159265358979323846264338327950288419716939937510 )
98  parameter( mu_zero = pi * 4.d-7)
99 end module helena_constants
100 
102 
103 contains
104 
105 function fdfdpsi(psi_n)
106 use helena_profiles
107 use itm_types
108 implicit none
109 real (r8) :: fdfdpsi, psi_n, dpsi
110 integer :: n_int
111 
112 dpsi = 1. /float(n_prof - 1)
113 
114 n_int = max(int((n_prof-1)*psi_n) + 1,1)
115 n_int = min(n_int,n_prof-1)
116 
117 fdfdpsi = ( fdf_dpsi(n_int) + (psi_n - dpsi * (n_int-1))/dpsi * (fdf_dpsi(n_int+1)-fdf_dpsi(n_int)) )
118 
119 return
120 end function fdfdpsi
121 
122 function dpdpsi(psi_n)
123 use helena_profiles
124 use itm_types
125 implicit none
126 real (r8) :: dpdpsi, psi_n, dpsi, tmp
127 integer :: n_int
128 
129 dpsi = 1. /float(n_prof - 1)
130 
131 n_int = max(int((n_prof-1)*psi_n) + 1,1)
132 n_int = min(n_int,n_prof-1)
133 
134 dpdpsi = ( dp_dpsi(n_int) + (psi_n - dpsi * (n_int-1))/dpsi * (dp_dpsi(n_int+1)-dp_dpsi(n_int)) )
135 
136 return
137 end function dpdpsi
138 
139 function fdia(psi_n)
140 use helena_profiles
141 use helena_axis
142 use helena_boundary
143 use itm_types
144 implicit none
145 real (r8) :: f2int, f0, fdia, psi_n, dpsi
146 integer :: n_int
147 
148 if (psi_n .lt. 0.) write(*,*) ' FDIA : ',psi_n
149 
150 dpsi = 1. /float(n_prof - 1)
151 
152 n_int = max(int((n_prof-1)*psi_n) + 1,1)
153 n_int = min(n_int,n_prof-1)
154 
155 f2int = ( f_psi(n_int) + (psi_n - dpsi * (n_int-1))/dpsi * (f_psi(n_int+1)-f_psi(n_int)) )
156 
157 f0 = rgeo * bgeo
158 
159 fdia = sqrt( abs(f0*f0 + 2. * f2int) )
160 
161 return
162 end function fdia
163 
164 function pressure(psi_n)
165 use helena_profiles
166 use helena_axis
167 use itm_types
168 implicit none
169 real (r8) :: pressure, psi_n, dpsi
170 integer :: n_int
171 
172 dpsi = 1. /float(n_prof - 1)
173 
174 n_int = max(int((n_prof-1)*psi_n) + 1,1)
175 n_int = min(n_int,n_prof-1)
176 
177 pressure = ( p_psi(n_int) + (psi_n - dpsi * (n_int-1))/dpsi * (p_psi(n_int+1)-p_psi(n_int)) )
178 
179 return
180 end function pressure
181 
182 function current_profile(psi_n)
183 use helena_profiles
184 use itm_types
185 implicit none
186 real (r8) :: current_profile, psi_n, dpsi
187 integer :: n_int
188 
189 dpsi = 1. /float(n_prof - 1)
190 
191 n_int = max(int((n_prof-1)*psi_n) + 1,1)
192 n_int = min(n_int,n_prof-1)
193 
194 current_profile = zjz_psi(n_int) + (psi_n - dpsi * (n_int-1))/dpsi * (zjz_psi(n_int+1)-zjz_psi(n_int))
195 
196 return
197 end function current_profile
198 !****************************************************************************************************************
199 
200 subroutine helena21(R_bnd_in,Z_bnd_in,n_bnd_in, &
201  rgeo_in,zgeo_in, amin_in, &
202  ellip_in,tria_u_in,tria_l_in,quad_u_in,quad_l_in, &
203  bgeo_in, &
204  psi_in, pprime_in, ffprime_in, &
205  pressure_in, fdia_in, current_in, n_prof_in, iopt_p, iopt_f, &
206  nr_grid, np_grid, &
207  psi_out, pprime_out, ffprime_out, &
208  pressure_out, fdia_out, current_out, qprof_out, vprime, &
209  fraction_circ, moments, n_moments, &
210  surface_powers, surface_integrals, n_var_surfaces, n_int_surfaces, &
211  volume_powers, volume_integrals, n_var_volumes, n_int_volumes, n_psi_out, n_tht_out, &
212  amin_out, rgeo_out, zgeo_out, &
213  area_out, volume_out, betap_out, xip_out, xli_out, beta_out, &
214  r_axis_out, z_axis_out, b_axis_out, psi_axis_out, psi_bnd_out, &
215  rrflux,zzflux,psflux)
216 
217 !****************************************************************************************************************
218 !
219 ! Helena version 2.0
220 !
221 ! - removed all normalisations. Quantities are in S.I. units.
222 ! - improved(?) the tracing of flux surfaces (no iterations, should be even more reliable)
223 !
224 !
225 ! author : Guido Huysmans (Association Euratom-CEA)
226 ! date : 05/02/2009
227 ! version : 0.8
228 ! status : slowly progressing ...
229 !
230 !
231 ! to be done :
232 ! - adjust radial integration of dpdpsi and fdfdpsi to changing ps_axis (done?)
233 ! - change modules to derived types and arguments to subroutines
234 ! - do the mapping to straight field line coordinates (generalised including Boozer, Hamada)
235 ! - finding all the new bugs...
236 !
237 ! !!! - fdia and pressure spline if available, otherwise integrate from spline pprime,ffprime
238 !
239 !****************************************************************************************************************
240 use helena_grid
241 use helena_boundary
242 use helena_profiles
243 use helena_matrix
244 use helena_axis
245 use helena_elements
246 use helena_surfaces
247 use helena_phys
248 use helena_map
250 
251 use itm_types
252 implicit none
253 
254 integer :: n_int_surfaces, n_int_volumes, n_var_surfaces, n_var_volumes, n_moments, n_psi_out, n_tht_out, ioption
255 real (r8) :: rrflux(4,*),zzflux(4,*),psflux(4,*)
256 real (r8) :: r_bnd_in(*),z_bnd_in(*),pressure_in(*),fdia_in(*),current_in(*),psi_in(*), pprime_in(*), ffprime_in(*)
257 real (r8) :: bgeo_in,rgeo_in,zgeo_in,amin_in,ellip_in,tria_u_in,tria_l_in,quad_u_in,quad_l_in
258 integer :: n_bnd_in, n_prof_in, nr_grid, np_grid, iopt_p, iopt_f
259 real (r8) :: surface_powers(n_var_surfaces,n_int_surfaces),surface_integrals(n_psi_out,n_int_surfaces)
260 real (r8) :: volume_powers(n_var_volumes,n_int_volumes), volume_integrals(n_psi_out,n_int_volumes)
261 real (r8) :: psi_n, psi_out(*), pressure_out(*), fdia_out(*), current_out(*), pprime_out(*), ffprime_out(*)
262 real (r8) :: qprof_out(*), vprime(*), fraction_circ(*),moments(n_moments,*)
263 integer :: i, j, index, n_iter, ifail, inode, n_chi, ileft, iright
264 real (r8) :: s, error_iteration, error_large, error_current, small, ss, psi_plot
265 real (r8) :: fdf_error, t1, t2, amix, fmix, ymin, ymax
266 logical :: solve_only, rhs_only
267 !real (r8) :: pressure, fdia, fdfdpsi, dpdpsi, current_profile
268 real (r8) :: amin_out, rgeo_out, zgeo_out, area_out, volume_out, betap_out, xip_out, xli_out, beta_out
269 real (r8) :: r_axis_out, z_axis_out, b_axis_out, psi_axis_out, psi_bnd_out
270 real (r8),allocatable :: rho_out(:), xplot(:), qplot(:), pplot(:)
271 real (r8) :: qtmp
272 
273 call begplt('helena.ps')
274 
275 !----------------------------------------- initialise
276 write(*,*) '**********************************************'
277 write(*,*) '* HELENA 2.0 (alpha_21) *'
278 write(*,*) '**********************************************'
279 
280 write(*,*) ' nr, np : ',nr_grid,np_grid
281 write(*,*) ' n_var_surfaces,n_int_surfaces : ',n_var_surfaces,n_int_surfaces
282 write(*,*) ' n_var_volumes, n_int_volumes : ',n_var_volumes, n_int_volumes
283 write(*,*) ' n_psi, n_tht : ',n_psi_out,n_tht_out
284 
285 mf = 128
286 nr = nr_grid
287 np = 2*int((np_grid+1)/2)
288 n_iter = 50
289 n_chi = 64
290 error_iteration = 1.d-6
291 error_large = 1.d-4
292 error_current = 1.d-4
293 
294 bgeo = bgeo_in
295 
296 write(*,*) ' Bgeo : ',bgeo
297 
298 n_bnd = n_bnd_in
299 allocate(r_bnd(n_bnd),z_bnd(n_bnd))
300 r_bnd(1:n_bnd) = r_bnd_in(1:n_bnd)
301 z_bnd(1:n_bnd) = z_bnd_in(1:n_bnd)
302 
303 call fshape
304 
305 n_prof = n_prof_in
306 
307 
308 call initialise_profiles(n_prof_in,iopt_p,iopt_f,psi_in, pprime_in, ffprime_in,pressure_in, fdia_in, current_in)
309 
310 call initialise_grid
311 
313 
314 solve_only = .false.
315 rhs_only = .false.
316 amix = 0.e0_r8
317 fmix = 0.e0_r8
318 
319 !---------------------------------------- iteration for current profile
320 if (iopt_f .eq. 3) then
321 
322  do i=1, n_iter
323 
324  call gs_solve(n_iter,rhs_only,solve_only,error_large,amix,ifail)
325 
326  if (ifail .ne. 0 ) then
327  amix = (1.e0_r8 + amix) /2.e0_r8
328  write(*,'(A,f8.3)') ' increasing amix : ',amix
329  endif
330 
331  call update_fdf(fmix,fdf_error)
332 
333  write(*,'(A,e14.6)') ' fdf_error : ',fdf_error
334  if (fdf_error .lt. error_current) exit
335 
336  enddo
337 
338 endif
339 
340 n_iter = 100
341 solve_only = .false.
342 rhs_only = .false.
343 
344 call gs_solve(n_iter,rhs_only,solve_only,error_iteration,amix,ifail)
345 
346 !-------------------------------------- output quantities
347 call phys_values
348 
349 !call plot_solution
350 
351 n_psi = n_psi_out - 1 ! n_psi does not count the axis (only the flux surfaces traced)
352 
353 if (allocated(psi_values)) deallocate(psi_values)
354 if (allocated(flux_surfaces)) deallocate(flux_surfaces)
355 
356 allocate(psi_values(n_psi))
357 
358 small = 1.d-8
359 write(*,*) 'main : i ss psi_values'
360 do i=1,n_psi
361  ss = float(i)/float(n_psi)
362  psi_values(i) = ps_axis - (1.e0_r8 - small) * ss*ss * ps_axis
363  write(*,'(A,i4,2e14.6)') ' main : ',i,ss,psi_values(i)
364 enddo
365 
368 
369 !write(*,*) ' size surface_integrals : ',size(surface_integrals)
370 !call fluxsurface_integrals(surface_powers,n_int_surfaces,n_var_surfaces,surface_integrals)
371 !write(*,*) ' fluxsurface integrals (1) : '
372 !do i=1,n_psi_out
373 ! write(*,'(i5,15e12.4)') i,surface_integrals(i,1:n_int_surfaces)
374 !enddo
375 
376 write(*,*) 'profiles out : i psi_n psi_out fdia_out'
377 do i=1,n_psi+1
378  if (i.eq.1) then
379  psi_n = 0.e0_r8
380  psi_out(i) = - ps_axis + psi_in(n_prof_in)
381  else
382  psi_n = -(psi_values(i-1) - ps_axis) / ps_axis
383  psi_out(i) = - psi_values(i-1) + psi_in(n_prof_in)
384  endif
385  pprime_out(i) = dpdpsi(psi_n)
386  ffprime_out(i) = fdfdpsi(psi_n)
387  pressure_out(i) = pressure(psi_n)
388  fdia_out(i) = fdia(psi_n)
389  current_out(i) = current_profile(psi_n)
390 
391  write(*,'(A,i4,8e14.6)') 'profiles out : ',i,psi_n,psi_out(i),fdia_out(i)
392 enddo
393 
394 !call export_helena
395 
396 call helena_remesh(n_psi_out,n_tht_out,rrflux,zzflux,psflux)
397 
398 call helena_flux_surface_integrals(n_psi_out,n_tht_out,rrflux,zzflux,psflux, &
399  surface_powers,n_int_surfaces,n_var_surfaces,surface_integrals, &
400  qprof_out, vprime)
401 
402 do i=1, n_psi_out
403  qprof_out(i) = fdia_out(i) * qprof_out(i) / (2.e0_r8*pi)
404 enddo
405 
406 write(*,*) ' fluxsurface integrals (2) : ',n_int_surfaces
407 do i=1,n_psi_out
408  write(*,'(i5,15e12.4)') i,surface_integrals(i,1:n_int_surfaces),qprof_out(i),vprime(i)
409 enddo
410 
411 !call helena_mapping(RRflux,ZZflux,PSflux,n_tht_out,n_chi)
412 
413 call helena_volume_integrals(n_psi_out,n_tht_out,rrflux,zzflux,psflux, &
414  volume_powers,volume_integrals,n_var_volumes,n_int_volumes,n_psi+1)
415 
416 allocate(rho_out(n_psi_out))
417 
418 write(*,*) 'i psi_out rho_out volume_integrals(1:3) qprof_out qtmp abs(qtmp-qprof_out)/qprof_out fdia_out'
419 do i=1, n_psi_out
420 
421  rho_out(i) = sqrt(volume_integrals(i,2)/ (2.e0_r8*pi) / (pi * bgeo_in)) ! B at magnetic axis?
422 
423  qtmp = 0.e0_r8
424  if ( (i .gt. 1) .and. (i .lt. n_psi_out)) then
425  qtmp = -(volume_integrals(i+1,2) - volume_integrals(i-1,2)) / (4.*pi*pi) / (psi_out(i+1)-psi_out(i-1))
426  endif
427 
428  write(*,'(i5,20f12.6)') i,psi_out(i),rho_out(i),volume_integrals(i,1:3),qprof_out(i),qtmp,abs(qtmp-qprof_out(i))/qprof_out(i),&
429  fdia_out(i)
430 
431 enddo
432 
433 
434 !call helena_moments(RRflux,ZZflux,n_psi_out,n_tht_out,moments,n_moments)
435 
436 call helena_circulating(n_psi_out,n_tht_out,rrflux,zzflux,psflux,fraction_circ)
437 fraction_circ(1) = 1.e0_r8
438 
439 area_out = area
440 volume_out = volume
441 betap_out = beta_p
442 xip_out = current
443 xli_out = 0.e0_r8
444 beta_out = beta_t
445 r_axis_out = r_axis
446 z_axis_out = z_axis
447 b_axis_out = b_axis
448 psi_axis_out = ps_axis
449 psi_bnd_out = psi_out(n_psi_out)
450 amin_out = amin
451 rgeo_out = rgeo
452 zgeo_out = zgeo
453 
454 
455 allocate(xplot(2*n_psi_out),pplot(2*n_psi_out),qplot(2*n_psi_out))
456 
457 do i=1,n_psi_out
458  ileft = (i-1)*n_tht_out + n_tht_out /2.e0_r8 + 1
459  iright = (i-1)*n_tht_out + 1
460  xplot(n_psi_out+i) = rrflux(1,ileft)
461  xplot(n_psi_out-i+1) = rrflux(1,iright)
462  pplot(n_psi_out+i) = pressure_out(i)
463  pplot(n_psi_out-i+1) = pressure_out(i)
464  qplot(n_psi_out+i) = qprof_out(i)
465  qplot(n_psi_out-i+1) = qprof_out(i)
466 enddo
467 
468 call lincol(0)
469 call lplot(3,2,1,xplot,pplot,2*n_psi_out,1,'pressure [Pa]',13,'R [m]',5,' ',1)
470 !DPC infinite loop? call lplot(3,3,1,xplot,qplot,2*n_psi_out,1,'q-profile',9,'R [m]',5,' ',1)
471 
472 call lblbot('HELENA_2(alpha)',15)
473 
474 call finplt
475 
476 deallocate(aa,bb,fr,dp_dpsi,fdf_dpsi,p_psi,f_psi)
477 deallocate(elm_list, index_list, index_inverse)
478 deallocate(rr, zz, psi)
479 !DPC
480 deallocate(flux_surfaces,r_bnd,z_bnd,psi_values,zjz_psi)
481 
482 end subroutine helena21
483 
484 subroutine helena_mapping(RR,ZZ,PSI,n_tht,n_chi)
485 !-----------------------------------------------------------------------
486 ! SUBROUTINE TO CALCULATE THE METRIC COEFFICIENTS NEEDED FOR CASTOR/MISHKA
487 ! a straight field line flux surface coordinate system with a regular
488 ! toroidal angle.
489 !-----------------------------------------------------------------------
491 use helena_axis
492 use helena_profiles
493 use helena_surfaces
494 use helena_map
495 use helena_gauss_4
496 use itm_types
497 implicit none
498 
499 real (r8) :: rr(4,*),zz(4,*),psi(4,*)
500 real (r8), allocatable :: cchi(:,:), schi(:,:), xchi(:,:), ychi(:,:), chikn(:)
501 real (r8), allocatable :: s_values(:)
502 integer, allocatable :: ijchi(:,:)
503 logical :: chin
504 
505 real (r8) :: sumq, sumqr, zsumq, zsumqr, psi_n, psir, psirr, ejac, er, bigr
506 real (r8) :: s, maxerr, x, xr, xs, xrs, xrr, xss, y, yr, ys, yrs, yrr, yss
507 real (r8) :: dum, dum1, dum2, dum3, dum4, qq, dqq, rb, drb
508 real (r8) :: dchi, chir, chis, chirs, chirr, psix, psiy, chix, chiy, zchi
509 real (r8) :: errj, serr, cerr, chiss, ejac2, a0, a1, a2, a3, s1, s2, s3
510 integer :: n_tht, n_chi, i,j,k, i_elm, node1, node2, node3, node4, no, nom, nop
511 integer :: jbase, n1, n2, n3, n4, ierr, jerr, ifail
512 !real (r8) :: fdia, fdfdpsi
513 real (r8) :: psi_tmp,psir_tmp,psis_tmp,psirs_tmp,psirr_tmp,psiss_tmp
514 
515 write(*,*) '********************************'
516 write(*,*) '* helena mapping *'
517 write(*,*) '********************************'
518 write(*,*) ' n_tht, n_chi : ',n_tht, n_chi
519 
520 !---------------------------------------------------------------------
521 maxerr = -1.d20
522 
523 
524 allocate(s_values(n_psi+1),cchi(4,(n_psi+1)*n_tht),schi((n_psi+1),n_chi),xchi((n_psi+1),n_chi),ychi((n_psi+1),n_chi))
525 allocate(chikn(n_chi),ijchi((n_psi+1),n_chi))
526 allocate(q_map(n_psi+1),dq_map(n_psi+1))
527 
528 do i=1,n_psi
529  s_values(i) = float(i)/float(n_psi)
530 enddo
531 
532 !------------------------------------------ - Q PROFILE ----------------
533 ! - DQ/DS PROFILE
534 ! - CHI VALUES AT THETA NODES
535 do i = 2, n_psi+1
536 
537  sumq = 0.e0_r8
538  sumqr = 0.e0_r8
539  psi_n = s_values(i-1)**2
540 
541  psir = - ps_axis * 2.e0_r8*s_values(i-1) / (2.e0_r8*REAL(n_psi))
542  psirr = - ps_axis * 2.e0_r8 / (2.e0_r8*REAL(n_psi))**2
543 
544  do j = 1, n_tht - 1
545 
546  node1 = (i-2)*n_tht + j
547  node2 = node1 + 1
548  node3 = node2 + n_tht
549  node4 = node1 + n_tht
550 
551  write(*,'(A,i5,4e16.8)') ' node 1 : ',node1,psi(:,node1)
552  write(*,'(A,i5,4e16.8)') ' node 2 : ',node2,psi(:,node2)
553  write(*,'(A,i5,4e16.8)') ' node 3 : ',node3,psi(:,node3)
554  write(*,'(A,i5,4e16.8)') ' node 4 : ',node4,psi(:,node4)
555 
556  do k = 1,4
557 
558  s = xgauss(k)
559 
560  CALL interp(rr(1,node1),rr(1,node2),rr(1,node3),rr(1,node4),+1.e0_r8,s, x,xr,xs,xrs,xrr,xss)
561  CALL interp(zz(1,node1),zz(1,node2),zz(1,node3),zz(1,node4),+1.e0_r8,s, y,yr,ys,yrs,yrr,yss)
562 
563 CALL interp(psi(1,node1),psi(1,node2),psi(1,node3),psi(1,node4),1.e0_r8,s,psi_tmp,psir_tmp,psis_tmp,psirs_tmp,psirr_tmp,psiss_tmp)
564  write(*,'(A,i5,12e12.4)') ' 1 : ',i,s_values(i-1),s,ps_axis,psi_tmp,psir_tmp,psir,psirr_tmp,psirr
565 
566  ejac = xr*ys - xs*yr
567  er = xrr*ys + xr*yrs - xrs*yr - xs*yrr
568  bigr = x
569  sumq = sumq - wgauss(k) * ejac / ( bigr * abs(psir))
570  sumqr = sumqr + psirr * ejac / ((psir**2)*bigr)* wgauss(k)
571  sumqr = sumqr - er / (bigr*psir) * wgauss(k)
572  sumqr = sumqr + ejac * xr / ((bigr**2)*psir) * wgauss(k)
573 
574  enddo
575 
576  cchi(1,(i-1)*n_tht+j+1) = sumq
577  cchi(2,(i-1)*n_tht+j+1) = sumqr
578 
579  CALL interp(rr(1,node1),rr(1,node2),rr(1,node3),rr(1,node4),+1.e0_r8,1.e0_r8,x,xr,xs,xrs,xrr,xss)
580  CALL interp(zz(1,node1),zz(1,node2),zz(1,node3),zz(1,node4),+1.e0_r8,1.e0_r8,y,yr,ys,yrs,yrr,yss)
581 
582 
583  CALL interp(psi(1,node1),psi(1,node2),psi(1,node3),psi(1,node4), &
584  1.e0_r8,1.e0_r8,psi_tmp,psir_tmp,psis_tmp,psirs_tmp,psirr_tmp,psiss_tmp)
585  write(*,'(A,i5,12e12.4)') ' end : ',i,s_values(i-1),ps_axis,psi_tmp, &
586  psir_tmp,psir,psirr_tmp,psirr
587 
588 
589  ejac = xr*ys - xs*yr
590  er = xrr*ys + xr*yrs - xrs*yr - xs*yrr
591  bigr = x
592 
593  zsumq = - ejac / ( bigr * abs(psir))
594  zsumqr = + psirr * ejac / (psir**2 *bigr) - er / (bigr*psir) + ejac*xr/((bigr**2) * psir)
595 
596  cchi(3,(i-1)*n_tht+j+1) = zsumq
597  cchi(4,(i-1)*n_tht+j+1) = zsumqr
598 
599  enddo
600 
601  cchi(1,(i-1)*n_tht+1) = 0.e0_r8
602  cchi(2,(i-1)*n_tht+1) = 0.e0_r8
603 
604  node1 = (i-1)*n_tht + 1
605  node2 = node1 + 1
606  node3 = node2 + n_tht
607  node4 = node1 + n_tht
608 
609  CALL interp(rr(1,node1),rr(1,node2),rr(1,node3),rr(1,node4),+1.e0_r8,-1.e0_r8,x,xr,xs,xrs,xrr,xss)
610  CALL interp(zz(1,node1),zz(1,node2),zz(1,node3),zz(1,node4),+1.e0_r8,-1.e0_r8,y,yr,ys,yrs,yrr,yss)
611 
612  ejac = xr*ys - xs*yr
613  er = xrr*ys + xr*yrs - xrs*yr - xs*yrr
614  bigr = x
615 
616  zsumq = - ejac / (bigr * abs(psir))
617  zsumqr = + psirr * ejac / (psir**2 *bigr) - er / (bigr*psir) + ejac*xr/((bigr**2) * psir)
618 
619  cchi(3,(i-1)*n_tht+1) = zsumq
620  cchi(4,(i-1)*n_tht+1) = zsumqr
621 
622  q_map(i) = 0.5e0_r8/pi * sumq * fdia(psi_n)
623  dq_map(i) = 0.5e0_r8/pi * ( sumqr * fdia(psi_n) + sumq*fdfdpsi(psi_n)/fdia(psi_n) /(2.e0_r8*(n_psi-1)))
624 
625  write(*,*) i,q_map(i),dq_map(i)
626 
627 enddo
628 
629 q_map(1) = fdia(0.e0_r8) /(2.e0_r8*sqrt(crr_axis*czz_axis)*r_axis)
630 dq_map(1) = 0.e0_r8
631 
632 do i = 2, n_psi
633 
634  psi_n = s_values(i)**2
635 
636  do j = 1, n_tht
637 
638  dum = cchi(1,i*n_tht)
639 
640  no = (i-1)*n_tht + j
641 
642  cchi(1,no) = 2.e0_r8*pi*cchi(1,no) / dum
643  dum2 = cchi(2,i*n_tht)
644  cchi(2,no) = 2.e0_r8*pi*cchi(2,no) / dum
645  cchi(3,no) = 2.e0_r8*pi*cchi(3,no) / dum
646  cchi(4,no) = 2.e0_r8*pi*cchi(4,no) / dum
647 
648  qq = q_map(i)
649  dqq = dq_map(i)
650  rb = fdia(psi_n)
651  drb = fdfdpsi(psi_n) / rb / (2*(n_psi-1))
652 
653  cchi(2,no)= +(dqq/qq - drb/rb) * cchi(1,no) - cchi(2,no)
654  cchi(4,no)= +(dqq/qq - drb/rb) * cchi(3,no) - cchi(4,no)
655 
656  enddo
657 
658 enddo
659 
660 WRITE(*,'(A,f8.4)') ' Q ON AXIS = ',q_map(1)
661 WRITE(*,'(A,f8.4)') ' Q AT BOUNDARY = ',q_map(n_psi)
662 
663 !--------------------------- DETERMINE POSITIONS OF EQUIDISTANT CHI'S --
664 ! AND CALCULATE MATRIX ELEMENTS -------------
665 
666 allocate(gem11(n_psi,n_chi),gem12(n_psi,n_chi),gem22(n_psi,n_chi),gem33(n_psi,n_chi))
667 allocate(rr_map(n_psi,n_chi), zz_map(n_psi,n_chi))
668 
669 do j=1,n_chi
670  chikn(j) = 2.e0_r8 * pi * REAL(j-1)/REAL(n_chi)
671 enddo
672 
673 do i=1,n_psi-1
674 
675  psi_n = s_values(i+1)**2
676  psir = - ps_axis * 2.e0_r8 * s_values(i+1) / (2.e0_r8*REAL(n_psi))
677 
678 !-------------------------- FIRST POINT IS KNOWN -----------------------
679  k = 1
680  s = -1.e0_r8
681  schi(i,1) = s
682  ijchi(i,1) = k
683 
684  node1 = (i-1)*n_tht + k
685  node2 = node1 + 1
686  node3 = node2 + n_tht
687  node4 = node1 + n_tht
688 
689  CALL interp(rr(1,node1),rr(1,node2),rr(1,node3),rr(1,node4),1.e0_r8,s,xchi(i,1),xr,xs,xrs,xrr,xss)
690  CALL interp(zz(1,node1),zz(1,node2),zz(1,node3),zz(1,node4),1.e0_r8,s,ychi(i,1),yr,ys,yrs,yrr,yss)
691  CALL interp(cchi(1,node1),cchi(1,node2),cchi(1,node3),cchi(1,node4),1.e0_r8,s,dchi,chir,chis,chirs,chirr,chiss)
692 
693  CALL interp(psi(1,node1),psi(1,node2),psi(1,node3),psi(1,node4),1.e0_r8,s,psi_tmp,psir_tmp,psis_tmp,psirs_tmp,psirr_tmp,psiss_tmp)
694 
695  write(*,'(A,i5,8e12.4)') ' 2 : ',i,s_values(i+1),ps_axis,psi_tmp,psir_tmp
696 
697 !-----------------------------------------------------------------------
698  ejac = (xr*ys-xs*yr)
699  ejac2 = ejac**2
700 
701 !----------------------------- DATA FOR VECTOR PLOT TO FILE 21 -----
702  psix = psir * ys / ejac
703  psiy = - psir * xs / ejac
704  chix = (chir * ys - chis * yr) / ejac
705  chiy = (-chir * xs + chis * xr)/ ejac
706 ! WRITE(21,61) SQRT(ZPSI),DCHI,XCHI(NO),YCHI(NO),PSIX,PSIY,CHIX,CHIY
707 
708 !----------------------------------------------------------------------
709  gem11(i,1) = psir**2 * (xs**2 + ys**2) / ejac2
710  gem12(i,1) = ( chir * psir * (xs**2 + ys**2) - chis * psir * (xr*xs + yr*ys) ) / ejac2
711  gem33(i,1) = xchi(i,1)
712  rr_map(i,1)= xchi(i,1)
713  zz_map(i,1)= ychi(i,1)
714 
715 !------------------------------------ CHECK JACOBIAN -----------------
716  dum1 = fdia(psi_n)**2 / (q_map(i)**2 * gem33(i,1))
717  dum2 = gem11(i,1) * (chix**2 + chiy**2)
718  dum3 = gem12(i,1)
719  dum4 = dum2 - dum3*dum3
720  errj = abs(dum4-dum1)
721 
722  IF (errj.GT.maxerr) THEN
723  maxerr=errj
724  ierr = i
725  jerr = j
726  serr = s_values(i)
727  cerr = dchi
728  ENDIF
729 
730 !---------------------------------------------------------------------
731  jbase = 2
732 
733  do k = 1,n_tht-1
734 
735  chin =.false.
736 
737  do j = jbase,n_chi
738 
739  zchi = chikn(j)
740 
741  IF (((cchi(1,(i-1)*n_tht+k).LE.zchi).AND.(cchi(1,(i-1)*n_tht+k+1) .GE.zchi)) ) THEN
742 
743  chin = .true.
744  nom = (i-1)*n_tht + k
745  nop = nom + 1
746  a3 = (cchi(1,nom)+cchi(3,nom)-cchi(1,nop)+cchi(3,nop))/4.e0_r8
747  a2 = (- cchi(3,nom) + cchi(3,nop))/4.e0_r8
748  a1=(-3*cchi(1,nom)-cchi(3,nom)+3*cchi(1,nop)-cchi(3,nop))/4.e0_r8
749  a0=( 2*cchi(1,nom)+cchi(3,nom)+2*cchi(1,nop)-cchi(3,nop))/4.e0_r8 - zchi
750 
751  CALL solvp3(a0,a1,a2,a3,s,s2,s3,ifail)
752 
753  IF (ifail.EQ.0) THEN
754 
755  schi(i,j) = s
756  ijchi(i,j) = k
757 
758  node1 = (i-1)*n_tht + k
759  node2 = node1 + 1
760  node3 = node2 + n_tht
761  node4 = node1 + n_tht
762 
763  CALL interp(rr(1,node1),rr(1,node2),rr(1,node3),rr(1,node4),-1.e0_r8,s,xchi(i,j),xr,xs,xrs,xrr,xss)
764  CALL interp(zz(1,node1),zz(1,node2),zz(1,node3),zz(1,node4),-1.e0_r8,s,ychi(i,j),yr,ys,yrs,yrr,yss)
765  CALL interp(cchi(1,node1),cchi(1,node2),cchi(1,node3),cchi(1,node4),-1.e0_r8,s,dchi,chir,chis,chirs,chirr,chiss)
766 
767 !-----------------------------------------------------------------
768  ejac = (xr*ys-xs*yr)
769  ejac2 = ejac**2
770 
771 !-------------------------- DATA FOR VECTOR PLOT TO FILE 21 -----
772  psix = psir * ys / ejac
773  psiy = - psir * xs / ejac
774  chix = (chir * ys - chis * yr) / ejac
775  chiy = (-chir * xs + chis * xr)/ ejac
776 
777 ! WRITE(21,61) SQRT(ZPSI),DCHI,XCHI(NO),YCHI(NO),PSIX,PSIY,CHIX,CHIY
778 !----------------------------------------------------------------
779 
780  gem11(i,j) = psir**2 * (xs**2 + ys**2) / ejac2
781  gem12(i,j) = ( chir * psir * (xs**2 + ys**2) - chis * psir * (xr*xs + yr*ys) ) / ejac2
782  gem33(i,j) = xchi(i,j)**2
783  rr_map(i,j) = xchi(i,j)
784  zz_map(i,j) = ychi(i,j)
785 
786 !------------------------------ CHECK JACOBIAN -----------------
787  dum1 = fdia(psi_n)**2 / (q_map(i)**2 * gem33(i,j)) !!!!!! check if psi_n defined
788  dum2 = gem11(i,j) * (chix**2 + chiy**2)
789  dum3 = gem12(i,j)
790  dum4 = dum2 - dum3*dum3
791  errj = abs(dum4-dum1)
792  IF (errj.GT.maxerr) THEN
793  maxerr=errj
794  ierr = i
795  jerr = j
796  serr = s_values(i)
797  cerr = dchi
798  ENDIF
799 !---------------------------------------------------------------------
800  ELSE
801  WRITE(20,*) 'ERROR IN SOLVP3 I,J,K : ',i,j,k,s,s2,s3
802  WRITE(*,*) a0,a1,a2,a3,zchi
803  WRITE(*,*) cchi(1,(i-1)*n_tht+k),cchi(1,(i-1)*n_tht+k+1)
804  ENDIF
805  ELSEIF (chin) THEN
806  jbase = j
807  exit
808  ENDIF
809 
810  enddo
811  enddo
812 enddo
813 
814 WRITE(*,*)
815 WRITE(*,*) '***************************************************'
816 WRITE(*,'(3e12.4,2i5)') maxerr,serr,cerr,ierr,jerr
817 WRITE(*,*) '***************************************************'
818 
819 n_psi_map = n_psi
820 n_chi_map = n_chi
821 
822 RETURN
823 END subroutine helena_mapping
824 
825 
826 subroutine helena_moments(RRflux,ZZflux,nr_flux,np_flux,moments,n_moments)
827 !----------------------------------------------------------------------
828 ! subroutine finds the Shafranov shift, ellipticity and triangularity
829 ! as a function of radius (flux).
830 !
831 ! moments(1,:) : minor radius (R_east - R_west) / 2.
832 ! moments(2,:) : Shafranov shift (R_east + R_west)/2 - R_geo
833 ! moments(3,:) : (Z_east - Z_west)/2. - Z_geo
834 ! moments(4,:) : Z_top/((R_east - R_west)/2.)
835 ! moments(5,:) : Z_low/((R_east - R_west)/2.)
836 ! moments(6,:) : (R_top - (R_east + R_west)/2.)/((R_east - R_west)/2.)
837 ! moments(7,:) : (R_low - (R_east + R_west)/2.)/((R_east - R_west)/2.)
838 !----------------------------------------------------------------------
840 use helena_axis
841 use itm_types
842 implicit none
843 real (r8) :: rrflux(4,*),zzflux(4,*),moments(n_moments,*)
844 integer :: nr_flux, np_flux, n_moments
845 real (r8) r,sum1,sum2,sumr,b02max,s,ws,rrg1,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss, &
846  zzg1,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,r_geo,z_geo,a_minor, &
847  zzm,zzmr,zzp,zzpr,aa,bb,cc,det,r_top,dummy,z_top, &
848  r_east,r_west,z_east,z_west,r_mid,z_mid,radius
849 integer i,j,n1,n2,n3,n4,ngs
850 
851 
852 
853 r_geo = ( rrflux(1,(nr_flux-1)*np_flux + 1) + rrflux(1,(nr_flux-1)*np_flux + np_flux/2 + 1)) /2.
854 z_geo = ( zzflux(1,(nr_flux-1)*np_flux + 1) + zzflux(1,(nr_flux-1)*np_flux + np_flux/2 + 1)) /2.
855 a_minor = abs( rrflux(1,(nr_flux-1)*np_flux + 1) - rrflux(1,(nr_flux-1)*np_flux + np_flux/2 + 1)) /2.
856 
857 write(*,*) ' moments : ',r_geo,z_geo
858 
859 moments(n_moments,1:nr_flux) = 0.e0_r8
860 
861 moments(1,1) = 0.e0_r8
862 moments(2,1) = rrflux(1,1) - r_geo
863 moments(3,1) = zzflux(1,1) - z_geo
864 moments(4,1) = sqrt(crr_axis / czz_axis)
865 moments(5,1) = sqrt(crr_axis / czz_axis)
866 moments(6,1) = 0.e0_r8
867 moments(7,1) = 0.e0_r8
868 
869 do i = 2, nr_flux
870 
871  do j = 1, np_flux - 1
872 
873  n1 = (i-1)*np_flux + j
874  n2 = (i-1)*np_flux + j + 1
875 
876  if (zzflux(3,n1)*zzflux(3,n2) .le. 0.e0_r8) then
877 !------------------------------------- QUAD. EQ FOR S VALUE AT MINIMUM -
878 
879  zzm = zzflux(1,n1)
880  zzmr = zzflux(3,n1)
881  zzp = zzflux(1,n2)
882  zzpr = zzflux(3,n2)
883  aa = 3.e0_r8 * (zzm + zzmr - zzp + zzpr ) / 4.e0_r8
884  bb = ( - zzmr + zzpr ) / 2.e0_r8
885  cc = ( - 3.e0_r8*zzm - zzmr + 3.e0_r8*zzp - zzpr) / 4.e0_r8
886  det = bb*bb - 4.e0_r8*aa*cc
887  s = root(aa,bb,cc,det,1.e0_r8)
888 
889  if (abs(s) .GT. 1.e0_r8) then
890  s = root(aa,bb,cc,det,-1.e0_r8)
891  endif
892 
893  call cub1d(rrflux(1,n1),rrflux(3,n1),rrflux(1,n2),rrflux(3,n2),s,r_top,dummy)
894  call cub1d(zzflux(1,n1),zzflux(3,n1),zzflux(1,n2),zzflux(3,n2),s,z_top,dummy)
895 
896  r_east = rrflux(1,(i-1)*np_flux + 1)
897  r_west = rrflux(1,(i-1)*np_flux + np_flux/2 + 1)
898  z_east = zzflux(1,(i-1)*np_flux + 1)
899  z_west = zzflux(1,(i-1)*np_flux + np_flux/2 + 1)
900 
901  r_mid = (r_east + r_west)/2.e0_r8
902  z_mid = (z_east + z_west)/2.e0_r8
903  radius = abs(r_east - r_west)/2.e0_r8
904 
905  write(*,'(A,i3,4f12.6)') 'mom : ',i,r_mid,z_mid,r_top,z_top
906 
907  moments(1,i) = radius
908  moments(2,i) = (r_mid - r_geo)
909  moments(3,i) = (z_mid - z_geo)
910 
911  if ( z_top - z_mid .gt. 0.e0_r8) then
912  moments(4,i) = (z_top - z_mid) / radius
913  moments(6,i) = -(r_top - r_mid) / radius
914  else
915  moments(5,i) = -(z_top - z_mid) / radius
916  moments(7,i) = -(r_top - r_mid) / radius
917  endif
918 
919  endif
920  enddo
921 
922 enddo
923 
924 !do i=1,nr_flux
925 ! write(*,'(i5,7f12.6)') i,moments(1:7,i)
926 !enddo
927 
928 return
929 end subroutine helena_moments
930 
931 
932 subroutine helena_circulating(nr_flux,np_flux,RRflux,ZZflux,PSflux,fraction_circ)
933 !----------------------------------------------------------------------
934 ! subroutine for the fraction of circulating (non-trapped) particles
935 !----------------------------------------------------------------------
936 use helena_gauss_4
937 use helena_axis
939 use itm_types
940 implicit none
941 real (r8),allocatable:: b0max(:),b02av(:),rav(:),sumk(:)
942 real (r8) :: rrflux(4,*),zzflux(4,*),psflux(4,*),fraction_circ(*)
943 integer :: nr_flux, np_flux
944 !real (r8) :: fdia
945 real (r8) r,sum1,sum2,sumr,b02max,s,ws, &
946  rrg1,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss, &
947  zzg1,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss, &
948  psg1,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss, &
949  rzjac,gradps2,zjdchi,psi_n,bphi,b02,b0,bm,zlam,sum
950 integer i,j,n1,n2,n3,n4,ngs,nk,k
951 
952 !---------------------- find Bmax and B^2 average on every surface
953 
954 allocate(b0max(nr_flux),b02av(nr_flux),rav(nr_flux))
955 
956 r = +1.e0_r8
957 
958 do i=1, nr_flux - 1
959 
960  sum1 = 0.e0_r8
961  sum2 = 0.e0_r8
962  sumr = 0.e0_r8
963  b02max = -1.d20
964 
965  do j=1, np_flux
966 
967  n1 = (i-1)*np_flux + j
968  n2 = (i-1)*np_flux + j + 1
969  n3 = (i )*np_flux + j + 1
970  n4 = (i )*np_flux + j
971 
972  if (j .eq. np_flux) then
973  n1 = (i )*np_flux
974  n2 = (i )*np_flux - np_flux + 1
975  n3 = (i )*np_flux + 1
976  n4 = (i )*np_flux + np_flux
977  endif
978 
979 !------------------------------------- 4 POINT GAUSSIAN INT. IN S -----
980  do ngs = 1, 4
981 
982  s = xgauss(ngs)
983  ws = wgauss(ngs)
984 
985  CALL interp(rrflux(1,n1),rrflux(1,n2),rrflux(1,n3),rrflux(1,n4),r,s,rrg1,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss)
986  CALL interp(zzflux(1,n1),zzflux(1,n2),zzflux(1,n3),zzflux(1,n4),r,s,zzg1,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss)
987  CALL interp(psflux(1,n1),psflux(1,n2),psflux(1,n3),psflux(1,n4),r,s,psg1,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss)
988 
989  rzjac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
990 
991  gradps2 = dpsg1_dr**2 * (drrg1_ds**2 + dzzg1_ds**2) / rzjac**2
992 
993  zjdchi = rrg1 * rzjac / dabs(dpsg1_dr)
994 
995  psi_n = - (psg1 - ps_axis) / ps_axis
996 
997  bphi = fdia(psi_n) / rrg1
998 
999  b02 = bphi**2 + gradps2/rrg1**2
1000 
1001  sum1 = sum1 - ws * zjdchi
1002  sum2 = sum2 - ws * zjdchi * b02
1003  sumr = sumr - ws * zjdchi * rrg1
1004 
1005  if (b02 .gt. b02max) b02max = b02
1006 
1007  enddo
1008 
1009  enddo
1010 
1011  b02av(i+1) = sum2 / sum1
1012  b0max(i+1) = dsqrt(dabs(b02max))
1013  rav(i+1) = sumr / sum1
1014 
1015 enddo
1016 
1017 
1018 !----------------------------- calculate average term in integral
1019 nk=101
1020 allocate(sumk(nk))
1021 
1022 r = +1.e0_r8
1023 
1024 write(*,*) 'i+1 sqrt(psi_n) B02av B0max fraction_circ'
1025 do i= 1, nr_flux-1
1026 
1027  sum1 = 0.e0_r8
1028 
1029  sumk = 0.e0_r8
1030 
1031  do j=1, np_flux
1032 
1033  n1 = (i-1)*np_flux + j
1034  n2 = (i-1)*np_flux + j + 1
1035  n3 = (i )*np_flux + j + 1
1036  n4 = (i )*np_flux + j
1037 
1038  if (j .eq. np_flux) then
1039  n1 = (i )*np_flux
1040  n2 = (i )*np_flux - np_flux + 1
1041  n3 = (i )*np_flux + 1
1042  n4 = (i )*np_flux + np_flux
1043  endif
1044 
1045 !------------------------------------- 4 POINT GAUSSIAN INT. IN S -----
1046  do ngs=1,4
1047 
1048  s = xgauss(ngs)
1049  ws = wgauss(ngs)
1050 
1051  call interp(rrflux(1,n1),rrflux(1,n2),rrflux(1,n3),rrflux(1,n4),r,s,rrg1,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss)
1052  call interp(zzflux(1,n1),zzflux(1,n2),zzflux(1,n3),zzflux(1,n4),r,s,zzg1,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss)
1053  call interp(psflux(1,n1),psflux(1,n2),psflux(1,n3),psflux(1,n4),r,s,psg1,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss)
1054 
1055  rzjac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
1056 
1057  gradps2 = dpsg1_dr**2 * (drrg1_ds**2 + dzzg1_ds**2) / rzjac**2
1058 
1059  zjdchi = rrg1 * rzjac / dabs(dpsg1_dr)
1060 
1061  psi_n = - (psg1 - ps_axis) / ps_axis
1062 
1063  bphi = fdia(psi_n) / rrg1
1064 
1065  b02 = bphi**2 + gradps2/rrg1**2
1066 
1067  b0 = dsqrt(dabs(b02))
1068  bm = b0max(i+1)
1069 
1070  do k = 1, nk
1071 
1072  zlam = dble(k-1)/dble(nk-1)
1073 
1074  sumk(k) = sumk(k) - ws*zjdchi*dsqrt(dabs(1.-zlam*b0/bm))
1075 
1076  enddo
1077 
1078  sum1 = sum1 - ws * zjdchi
1079  enddo
1080 
1081  enddo
1082 
1083 !------------------------------------------ integrate over lambda
1084  sum = 0.e0_r8
1085 
1086  do k=2,nk-1
1087 
1088  zlam = float(k-1)/float(nk-1)
1089  sum = sum + zlam * sum1 / sumk(k)
1090 
1091  enddo
1092 
1093  fraction_circ(i+1) = (sum + 0.5e0_r8 * sum1/sumk(nk)) / float(nk-1)
1094  fraction_circ(i+1) = 0.75e0_r8 * fraction_circ(i+1) * b02av(i+1) / b0max(i+1)**2
1095 
1096 
1097  psi_n = - (psg1 - ps_axis) / ps_axis
1098  write(*,'(i5,4f12.6)') i+1,sqrt(psi_n),b02av(i+1),b0max(i+1),fraction_circ(i+1)
1099 
1100 enddo
1101 
1102 return
1103 end subroutine helena_circulating
1104 
1105 
1106 
1107 subroutine helena_volume_integrals(nr_flux,np_flux,RR_flux,ZZ_flux,PS_flux, &
1108  powers,volume_integrals,n_var,n_int,n_psi)
1109 !------------------------------------------------------------------------
1110 ! subroutines calculates some quantities which are volume integrals
1111 ! within a fluxsurface.
1112 !
1113 ! requires a mesh aligned on fluxsurface (helena_remesh)
1114 !
1115 ! 1) R 2) B_phi
1116 !------------------------------------------------------------------------
1117 use helena_gauss_4
1118 use helena_axis
1119 use helena_constants
1120 use itm_types
1121 implicit none
1122 
1123 real (r8) :: rr_flux(4,*),zz_flux(4,*), ps_flux(4,*)
1124 real (r8) :: powers(n_var,n_int),volume_integrals(n_psi,n_int)
1125 integer :: nr_flux, np_flux, n_var, n_int, n_psi
1126 !real (r8) :: fdia
1127 real (r8) r,wr,s,ws,rzjac,psi_n,bphi, &
1128  rrg1,drrg1_dr,drrg1_ds,zzg1,dzzg1_dr,dzzg1_ds,psg1,dpsg1_dr,dpsg1_ds
1129 integer i,j,n1,n2,n3,n4,ngr,ngs,m
1130 
1131 
1132 write(*,*) ' helena volume integrals : ',nr_flux,np_flux
1133 
1134 volume_integrals(1:n_psi,1:n_int) = 0.e0_r8
1135 
1136 do i=1,nr_flux-1
1137 
1138  volume_integrals(i+1,1:n_int) = volume_integrals(i,1:n_int)
1139 
1140  do j=1,np_flux
1141 
1142  n1 = (i-1)*np_flux + j
1143  n2 = (i-1)*np_flux + j + 1
1144  n3 = (i )*np_flux + j + 1
1145  n4 = (i )*np_flux + j
1146 
1147  if (j .eq. np_flux) then
1148  n1 = (i )*np_flux
1149  n2 = (i )*np_flux - np_flux + 1
1150  n3 = (i )*np_flux + 1
1151  n4 = (i )*np_flux + np_flux
1152  endif
1153 
1154  do ngr=1,4
1155 
1156  r = xgauss(ngr)
1157  wr = wgauss(ngr)
1158 
1159  do ngs=1,4
1160 
1161  s = xgauss(ngs)
1162  ws = wgauss(ngs)
1163 
1164  CALL interp2(rr_flux(1,n1),rr_flux(1,n2),rr_flux(1,n3),rr_flux(1,n4),r,s,rrg1,drrg1_dr,drrg1_ds)
1165  CALL interp2(zz_flux(1,n1),zz_flux(1,n2),zz_flux(1,n3),zz_flux(1,n4),r,s,zzg1,dzzg1_dr,dzzg1_ds)
1166  CALL interp2(ps_flux(1,n1),ps_flux(1,n2),ps_flux(1,n3),ps_flux(1,n4),r,s,psg1,dpsg1_dr,dpsg1_ds)
1167 
1168  rzjac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
1169  psi_n = - (psg1 - ps_axis) / ps_axis
1170 
1171  bphi = fdia(psi_n) / rrg1
1172 
1173  do m=1,n_int
1174 
1175  volume_integrals(i+1,m) = volume_integrals(i+1,m) &
1176  + rrg1**powers(1,m) * bphi**powers(2,m) * wr * ws * 2.e0_r8 *pi * rrg1 * rzjac ! 3D volume integral (not area)
1177 
1178  enddo
1179 
1180  enddo
1181 
1182  enddo
1183 
1184  enddo
1185 
1186 enddo
1187 
1188 return
1189 end subroutine helena_volume_integrals
1190 
1191 subroutine helena_remesh(nrnew,npnew,RRnew,ZZnew,PSInew)
1192 !------------------------------------------------------------------------
1193 ! subroutine calculates a new flux surface grid
1194 !------------------------------------------------------------------------
1195 use helena_surfaces
1196 use helena_elements
1197 use helena_grid
1198 use helena_axis
1199 use itm_types
1200 implicit none
1201 
1202 real (r8) :: rrnew(4,*),zznew(4,*),psinew(4,*), abltg(3), xtmp, tol_t
1203 real (r8),allocatable :: s_values(:),tht_start(:),tht_end(:)
1204 real (r8),allocatable :: sp1(:),sp2(:),sp3(:),sp4(:)
1205 real (r8) pi,dpsi_ds,tht_min,tht_max,rr1,rr2,ss1,ss2, &
1206  rrg1,drrg1_dr,drrg1_ds,zzg1,dzzg1_dr,dzzg1_ds,rrg2,drrg2_dr, &
1207  drrg2_ds,zzg2,dzzg2_dr,dzzg2_ds,tht1,tht2,tht_tmp,theta, &
1208  drr1,dss1,drr2,dss2,drrg1_dt,dzzg1_dt,drrg2_dt,dzzg2_dt, &
1209  rz1,rz2,drz1,drz2,rz0,a3,a2,a1,a0,t,t2,t3,ri,dri,si, &
1210  dsi,drrg1_drs,drrg1_drr,drrg1_dss,dzzg1_drs,dzzg1_drr, &
1211  dzzg1_dss,psg1,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss, &
1212  check,rad2,th_z,th_r,th_rr,th_zz,th_rz,dth_ds,dth_dr,dth_drr,dth_drs,dth_dss, &
1213  rzjac,ps_r,ps_z,ejac,ptjac,rt,st,dptjac_dr,dptjac_ds,rpt,spt, &
1214  dr_dpt,dz_dpt,dr_dz,dr_dr,ds_dz,ds_dr,dps_drr,dps_dzz,cx,cy,tn,tn2,cn
1215 integer nrnew,npnew,i,k,i_elm,node1,node2,node3,node4,j,ifail,inode
1216 
1217 if (nrnew .ne. n_psi+1) write(*,*) ' MAJOR PROBLEM in REMESH! nrnew <> n_psi+1'
1218 
1219 write(*,*) '**************************************'
1220 write(*,*) '* helena remesh : ',nrnew,npnew,'*'
1221 write(*,*) '**************************************'
1222 
1223 tol_t = 1.d-8 ! tolerance
1224 
1225 allocate(s_values(n_psi+1),tht_start(n_pieces_max),tht_end(n_pieces_max))
1226 
1227 rrnew(1:4,1:nrnew*npnew) = 0.e0_r8
1228 zznew(1:4,1:nrnew*npnew) = 0.e0_r8
1229 psinew(1:4,1:nrnew*npnew) = 0.e0_r8
1230 
1231 pi = 2.e0_r8*asin(1.e0_r8)
1232 
1233 do i=1,n_psi+1
1234  s_values(i) = float(i-1)/float(n_psi)
1235 enddo
1236 
1237 allocate(sp1(n_psi+1),sp2(n_psi+1),sp3(n_psi+1),sp4(n_psi+1))
1238 
1239 !call spline(n_psi+1,s_values,psi_values,0.,0.,1,sp1,sp2,sp3,sp4)
1240 
1241 do i=1,n_psi
1242 
1243 ! xtmp = spwert(n_psi,s_values(i),sp1,sp2,sp3,sp4,s_values,abltg)
1244 ! dpsi_ds = abltg(1)
1245 
1246  dpsi_ds = - ps_axis * 2.e0_r8*s_values(i+1) ! for an equidistant grid in s
1247 
1248  tht_min = 1d20
1249  tht_max = -1d20
1250 
1251  do k=1, flux_surfaces(i)%n_pieces
1252 
1253  rr1 = flux_surfaces(i)%r(1,k)
1254  rr2 = flux_surfaces(i)%r(3,k)
1255 
1256  ss1 = flux_surfaces(i)%s(1,k)
1257  ss2 = flux_surfaces(i)%s(3,k)
1258 
1259  i_elm = flux_surfaces(i)%elm(k)
1260 
1261  node1 = elm_list(1,i_elm)
1262  node2 = elm_list(2,i_elm)
1263  node3 = elm_list(3,i_elm)
1264  node4 = elm_list(4,i_elm)
1265 
1266  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),rr1,ss1,rrg1,drrg1_dr,drrg1_ds)
1267  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),rr1,ss1,zzg1,dzzg1_dr,dzzg1_ds)
1268  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),rr2,ss2,rrg2,drrg2_dr,drrg2_ds)
1269  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),rr2,ss2,zzg2,dzzg2_dr,dzzg2_ds)
1270 
1271  tht1 = atan2(zzg1-z_axis,rrg1-r_axis)
1272  tht2 = atan2(zzg2-z_axis,rrg2-r_axis)
1273 
1274  if (tht1 .lt. 0.e0_r8) tht1 = tht1 + 2.e0_r8*pi
1275  if (tht2 .lt. 0.e0_r8) tht2 = tht2 + 2.e0_r8*pi
1276 
1277  tht_start(k) = min(tht1,tht2)
1278  tht_end(k) = max(tht1,tht2)
1279 
1280  if ((tht_end(k) - tht_start(k)) .gt. 3.e0_r8*pi/4.e0_r8) then
1281  tht_tmp = tht_end(k)
1282  tht_end(k) = tht_start(k)
1283  tht_start(k) = tht_tmp - 2.e0_r8*pi
1284  endif
1285 
1286  tht_min = min(tht_min,tht_start(k))
1287  tht_max = max(tht_max,tht_end(k))
1288 
1289  enddo
1290 
1291  do j=1, npnew
1292 
1293  theta = 2.e0_r8 * pi * float(j-1)/float(npnew)
1294 
1295  if (theta .gt. tht_max) theta = theta - 2.e0_r8*pi
1296  if (theta .lt. tht_min) theta = theta + 2.e0_r8*pi
1297 
1298  do k=1, flux_surfaces(i)%n_pieces
1299 
1300  if ( (theta .ge. tht_start(k)) .and. (theta .le. tht_end(k)) ) then
1301 
1302  rr1 = flux_surfaces(i)%r(1,k); ss1 = flux_surfaces(i)%s(1,k)
1303  drr1 = flux_surfaces(i)%r(2,k); dss1 = flux_surfaces(i)%s(2,k)
1304  rr2 = flux_surfaces(i)%r(3,k); ss2 = flux_surfaces(i)%s(3,k)
1305  drr2 = flux_surfaces(i)%r(4,k); dss2 = flux_surfaces(i)%s(4,k)
1306 
1307  i_elm = flux_surfaces(i)%elm(k)
1308 
1309  node1 = elm_list(1,i_elm)
1310  node2 = elm_list(2,i_elm)
1311  node3 = elm_list(3,i_elm)
1312  node4 = elm_list(4,i_elm)
1313 
1314  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),rr1,ss1,rrg1,drrg1_dr,drrg1_ds)
1315  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),rr1,ss1,zzg1,dzzg1_dr,dzzg1_ds)
1316  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),rr2,ss2,rrg2,drrg2_dr,drrg2_ds)
1317  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),rr2,ss2,zzg2,dzzg2_dr,dzzg2_ds)
1318 
1319  drrg1_dt = drrg1_dr * drr1 + drrg1_ds * dss1
1320  dzzg1_dt = dzzg1_dr * drr1 + dzzg1_ds * dss1
1321  drrg2_dt = drrg2_dr * drr2 + drrg2_ds * dss2
1322  dzzg2_dt = dzzg2_dr * drr2 + dzzg2_ds * dss2
1323 
1324  rz1 = rrg1 * tan(theta) - zzg1
1325  rz2 = rrg2 * tan(theta) - zzg2
1326  drz1 = drrg1_dt * tan(theta) - dzzg1_dt
1327  drz2 = drrg2_dt * tan(theta) - dzzg2_dt
1328 
1329  rz0 = r_axis * tan(theta) - z_axis
1330 
1331  a3 = ( rz1 + drz1 - rz2 + drz2 )/4.e0_r8
1332  a2 = ( - drz1 + drz2 )/4.e0_r8
1333  a1 = (-3.e0_r8*rz1 - drz1 + 3.e0_r8*rz2 - drz2 )/4.e0_r8
1334  a0 = ( 2.e0_r8*rz1 + drz1 + 2.e0_r8*rz2 - drz2 )/4.e0_r8 - rz0
1335 
1336  call solvp3(a0,a1,a2,a3,t,t2,t3,ifail)
1337 
1338  if (abs(t) .le. 1.e0_r8+tol_t) then
1339 
1340  call cub1d(rr1, drr1, rr2, drr2, t, ri, dri)
1341  call cub1d(ss1, dss1, ss2, dss2, t, si, dsi)
1342 
1343  call interp(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),ri,si, &
1344  rrg1,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss)
1345  call interp(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),ri,si, &
1346  zzg1,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss)
1347  call interp(psi(:,node1),psi(:,node2),psi(:,node3),psi(:,node4),ri,si, &
1348  psg1,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss)
1349 
1350  check = atan2(zzg1- z_axis,rrg1-r_axis)
1351  if (check .lt. 0.e0_r8) check = check + 2.e0_r8*pi
1352 
1353  rad2 = (rrg1 - r_axis)**2 + (zzg1 - z_axis)**2
1354  th_z = (rrg1 - r_axis) / rad2
1355  th_r = - (zzg1 - z_axis) / rad2
1356 
1357  th_rr = 2*(zzg1 - z_axis) * (rrg1 - r_axis) / rad2**2
1358  th_zz = - th_rr
1359  th_rz = ( (zzg1 - z_axis)**2 - (rrg1 - r_axis)**2 ) / rad2**2
1360 
1361  dth_ds = th_r * drrg1_ds + th_z * dzzg1_ds
1362  dth_dr = th_r * drrg1_dr + th_z * dzzg1_dr
1363 
1364  dth_drr = th_rr * drrg1_dr * drrg1_dr + th_r * drrg1_drr + 2.* th_rz * drrg1_dr * dzzg1_dr &
1365  + th_zz * dzzg1_dr * dzzg1_dr + th_z * dzzg1_drr
1366 
1367  dth_drs = th_rr * drrg1_dr * drrg1_ds + th_rz * drrg1_dr * dzzg1_ds + th_r * drrg1_drs &
1368  + th_rz * dzzg1_dr * drrg1_ds + th_zz * dzzg1_dr * dzzg1_ds + th_z * dzzg1_drs
1369 
1370  dth_dss = th_rr * drrg1_ds * drrg1_ds + th_r * drrg1_dss + 2.* th_rz * drrg1_ds * dzzg1_ds &
1371  + th_zz * dzzg1_ds * dzzg1_ds + th_z * dzzg1_dss
1372 
1373  rzjac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
1374 
1375  ps_r = ( dzzg1_ds * dpsg1_dr - dzzg1_dr * dpsg1_ds) / rzjac
1376  ps_z = (- drrg1_ds * dpsg1_dr + drrg1_dr * dpsg1_ds) / rzjac
1377 
1378  ejac = (ps_r * th_z - ps_z * th_r)
1379  ptjac = (dpsg1_dr * dth_ds - dpsg1_ds * dth_dr)
1380 
1381  rt = - dpsg1_ds / ptjac
1382  st = dpsg1_dr / ptjac
1383 
1384  dptjac_dr = dpsg1_drr * dth_ds + dpsg1_dr * dth_drs - dpsg1_drs * dth_dr - dpsg1_ds * dth_drr
1385 
1386  dptjac_ds = dpsg1_drs * dth_ds + dpsg1_dr * dth_dss - dpsg1_dss * dth_dr - dpsg1_ds * dth_drs
1387 
1388  rpt = (-dptjac_dr * dth_ds / ptjac**2 + dth_drs/ptjac) * rt + (- dptjac_ds * dth_ds / ptjac**2 + dth_dss/ptjac) * st
1389 
1390  spt = ( dptjac_dr * dth_dr / ptjac**2 - dth_drr/ ptjac) * rt + ( dptjac_ds * dth_dr / ptjac**2 - dth_drs/ptjac) * st
1391 
1392  dr_dpt = - drrg1_drr * dth_ds * dpsg1_ds / ptjac**2 + drrg1_drs * (dth_ds * dpsg1_dr + dth_dr * dpsg1_ds) / ptjac**2 &
1393  + drrg1_dr * rpt + drrg1_ds * spt - drrg1_dss * dth_dr * dpsg1_dr / ptjac**2
1394 
1395  dz_dpt = - dzzg1_drr * dth_ds * dpsg1_ds / ptjac**2 + dzzg1_drs * (dth_ds * dpsg1_dr + dth_dr * dpsg1_ds) / ptjac**2 &
1396  + dzzg1_dr * rpt + dzzg1_ds * spt - dzzg1_dss * dth_dr * dpsg1_dr /ptjac**2
1397 
1398 
1399  rrnew(1,npnew*(i) + j) = rrg1
1400  zznew(1,npnew*(i) + j) = zzg1
1401 
1402  rrnew(2,npnew*(i) + j) = ( th_z / ejac) / (2.e0_r8*(nrnew-1)) * dpsi_ds
1403  zznew(2,npnew*(i) + j) = (- th_r / ejac) / (2.e0_r8*(nrnew-1)) * dpsi_ds
1404 
1405  rrnew(3,npnew*(i) + j) = + (- ps_z / ejac) / (npnew/pi)
1406  zznew(3,npnew*(i) + j) = + ( ps_r / ejac) / (npnew/pi)
1407 
1408  rrnew(4,npnew*(i) + j) = dr_dpt /(2.e0_r8*(nrnew-1)*(npnew)/pi) * dpsi_ds
1409  zznew(4,npnew*(i) + j) = dz_dpt /(2.e0_r8*(nrnew-1)*(npnew)/pi) * dpsi_ds
1410 
1411  psinew(1,npnew*(i) + j) = psi_values(i)
1412  psinew(2,npnew*(i) + j) = dpsi_ds / (2.e0_r8*(nrnew-1))
1413  psinew(3,npnew*(i) + j) = 0.e0_r8
1414  psinew(4,npnew*(i) + j) = 0.e0_r8
1415 
1416  else
1417 
1418  write(*,*) ' T TOO BIG : ',t,t2,t3
1419 
1420  endif
1421 
1422  endif
1423 
1424  enddo
1425 
1426  enddo
1427 
1428 enddo
1429 
1430 !----------------------------------- magnetic axis
1431 
1432 node1 = elm_list(1,ielm_ax)
1433 node2 = elm_list(2,ielm_ax)
1434 node3 = elm_list(3,ielm_ax)
1435 node4 = elm_list(4,ielm_ax)
1436 
1437 call interp(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),r_ax,s_ax,rrg1,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss)
1438 call interp(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),r_ax,s_ax,zzg1,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss)
1439 call interp(psi(:,node1),psi(:,node2),psi(:,node3),psi(:,node4),r_ax,s_ax,psg1,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss)
1440 
1441 ejac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
1442 dr_dz = - drrg1_ds / ejac
1443 dr_dr = + dzzg1_ds / ejac
1444 ds_dz = + drrg1_dr / ejac
1445 ds_dr = - dzzg1_dr / ejac
1446 
1447 dps_drr = dpsg1_drr * dr_dr * dr_dr + 2.*dpsg1_drs * dr_dr * ds_dr + dpsg1_dss * ds_dr * ds_dr
1448 dps_dzz = dpsg1_drr * dr_dz * dr_dz + 2.*dpsg1_drs * dr_dz * ds_dz + dpsg1_dss * ds_dz * ds_dz
1449 
1450 crr_axis = dps_drr / 2.e0_r8
1451 czz_axis = dps_dzz / 2.e0_r8
1452 
1453 !write(*,*) ' CRR, CZZ : ',CRR_axis,CZZ_axis
1454 
1455 cx = crr_axis
1456 cy = czz_axis
1457 
1458 do j=1,npnew
1459 
1460  inode = j
1461  rrnew(1,inode) = rrg1
1462  zznew(1,inode) = zzg1
1463 
1464  theta = float(j-1)/float(npnew) * 2.e0_r8*pi
1465 
1466  tn = tan(theta)
1467  tn2 = tn**2
1468  cn = cos(theta)
1469 
1470  if (theta .eq. pi/2.e0_r8) then
1471  rrnew(2,inode) = 0.e0_r8
1472  zznew(2,inode) = +1.e0_r8/(sqrt(abs(cy))*2.e0_r8*float(nrnew-1))
1473  rrnew(4,inode) = -1.e0_r8/(sqrt(abs(cy))*2.e0_r8*float(nrnew-1)*float(npnew)/pi)
1474  zznew(4,inode) = 0.e0_r8
1475  ELSEIF (theta .eq. (3.e0_r8*pi/2)) THEN
1476  rrnew(2,inode) = 0.e0_r8
1477  zznew(2,inode) = +1.e0_r8/(sqrt(abs(cy))*2.*float(nrnew-1))
1478  rrnew(4,inode) = -1.e0_r8/(sqrt(abs(cy))*2.*float(nrnew-1)*float(npnew)/pi)
1479  zznew(4,inode) = 0.e0_r8
1480  ELSE
1481  rrnew(2,inode) = + sign(1.e0_r8,cn)/(sqrt(abs(cx+cy*tn2))*2.e0_r8*float(nrnew-1))
1482  zznew(2,inode) = + abs(tn)/(sqrt(abs(cx+cy*tn2))*2.e0_r8*float(nrnew-1))
1483  rrnew(4,inode) = - (cx+cy*tn2)**(-1.5e0_r8) * cy * abs(tn) / (cn**2 * 2.e0_r8*float(nrnew-1)*float(npnew)/pi)
1484  zznew(4,inode) = + cx * (cx + cy*tn2)**(-1.5e0_r8) / (cn*abs(cn) * 2.e0_r8*float(nrnew-1)*float(npnew-1)/pi)
1485  ENDIF
1486  IF (theta .gt. pi) THEN
1487  zznew(2,inode) = - zznew(2,inode)
1488  rrnew(4,inode) = - rrnew(4,inode)
1489  ENDIF
1490  rrnew(3,inode) = 0.e0_r8
1491  zznew(3,inode) = 0.e0_r8
1492  psinew(1,inode) = ps_axis
1493 
1494 enddo
1495 
1496 !call plot_grid(RRnew,ZZnew,nrnew,npnew)
1497 
1498 return
1499 end subroutine helena_remesh
1500 
1501 
1502 subroutine export_helena
1503 use helena_boundary
1504 use helena_profiles
1505 use helena_phys
1506 use helena_grid
1507 use helena_axis
1508 use helena_constants
1509 use itm_types
1510 implicit none
1511 integer :: i
1512 
1513 write(*,*) ' export to HELENA namelist'
1514 
1515 open(20,file='helena.nml')
1516 write(20,*) ' &SHAPE IAS = 1, ISHAPE = 2,'
1517 write(20,'(A,i5,A,i5)') ' MFM= ',mf,', MHARM = ',mf/2
1518 do i=1,mf/2
1519  write(20,'(A,i4,A,e14.6,A,i4,A,e14.6)') ' FM(',2*i-1,')=',fr(2*i-1)/amin,' FM(',2*i,')=',fr(2*i)/amin
1520 enddo
1521 write(20,*) ' &END'
1522 write(20,*) ' &PROFILE '
1523 write(20,*) ' IPAI=7, EPI=1.0, FPI=1.0'
1524 write(20,*) ' IGAM=7'
1525 write(20,*) ' ICUR=2, ECUR=1.0, FCUR=1.0'
1526 write(20,*) ' NPTS = ',n_prof
1527 do i=1,n_prof
1528  write(20,'(A,i4,A,e12.4,A,i4,A,e12.4,A,i4,A,e12.4)') &
1529  ' DPR(',i,') = ',dp_dpsi(i),', DF2(',i,') = ',fdf_dpsi(i),', ZJZ(',i,') = ',zjz_psi(i)
1530 enddo
1531 write(20,*) ' &END'
1532 write(20,*) ' &PHYS '
1533 write(20,'(A,f10.6)') ' EPS = ',amin/rgeo
1534 write(20,'(A,f10.6)') ' ALFA = ',abs(amin**2 * bgeo / ps_axis)
1535 write(20,'(A,f10.6)') ' B = ',mu_zero * rgeo**2 * dp_dpsi(1)/fdf_dpsi(1)
1536 write(20,'(A,f10.6)') ' BETAP = ',beta_p
1537 write(20,'(A,f10.6)') ' XIAB = ',mu_zero * abs(current) / (amin * bgeo)
1538 write(20,'(A,f10.6)') ' RVAC = ',rgeo
1539 write(20,'(A,f10.6)') ' BVAC = ',bgeo
1540 write(20,*) ' &END'
1541 write(20,*) ' &NUM'
1542 write(20,*) ' NR = 51, NP = 33, NRMAP = 101, NPMAP = 129, NCHI = 128'
1543 write(20,*) ' NRCUR = 51, NPCUR = 33, ERRCUR = 1.e-5, NITER = 100, NMESH = 100'
1544 write(20,*) ' &END'
1545 write(20,*) ' &PRI NPR1=1 &END '
1546 write(20,*) ' &PLOT NPL1=1 &END '
1547 write(20,*) ' &BALL &END '
1548 close(20)
1549 return
1550 end subroutine export_helena
1551 
1552 subroutine phys_values
1553 use helena_grid
1554 use helena_elements
1555 use helena_gauss_4
1556 use helena_matrix
1557 use helena_constants
1558 use helena_axis
1559 use helena_boundary
1560 use helena_phys
1561 
1562 use itm_types
1563 implicit none
1564 integer :: nodes(4)
1565 real (r8) :: xx(4,4), xr(4,4), xs(4,4), yr(4,4), ys(4,4), xjac(4,4), ps(4,4), psn(4,4)
1566 real (r8) :: sum_p_area, sum_p_vol, sum_c_area, sum_vol, sum_area, zjz
1567 integer :: ngr, ngs, kf, kv, i, vertex
1568 !real (r8) :: dpdpsi, fdfdpsi, pressure
1569 
1570 sum_area = 0.e0_r8
1571 sum_vol = 0.e0_r8
1572 sum_p_vol = 0.e0_r8
1573 sum_p_area = 0.e0_r8
1574 sum_c_area = 0.e0_r8
1575 
1576 do i=1, n_elms
1577 
1578  nodes(1) = elm_list(1,i)
1579  nodes(2) = elm_list(2,i)
1580  nodes(3) = elm_list(3,i)
1581  nodes(4) = elm_list(4,i)
1582 
1583  xr = 0.e0_r8
1584  xs = 0.e0_r8
1585  yr = 0.e0_r8
1586  ys = 0.e0_r8
1587  xx = 0.e0_r8
1588  ps = 0.e0_r8
1589 
1590  do ngr = 1, 4 ! 4 Gaussian points
1591  do ngs = 1, 4 ! 4 Gaussian points
1592  do kf = 1, 4 ! 4 basis functions
1593  do kv = 1, 4 ! 4 vertices
1594 
1595  vertex = nodes(kv)
1596 
1597  xx(ngr,ngs) = xx(ngr,ngs) + rr(kf,vertex) * h(ngr,ngs,kv,kf)
1598  ps(ngr,ngs) = ps(ngr,ngs) + psi(kf,vertex) * h(ngr,ngs,kv,kf)
1599 
1600  xr(ngr,ngs) = xr(ngr,ngs) + rr(kf,vertex) * hr(ngr,ngs,kv,kf)
1601  xs(ngr,ngs) = xs(ngr,ngs) + rr(kf,vertex) * hs(ngr,ngs,kv,kf)
1602  yr(ngr,ngs) = yr(ngr,ngs) + zz(kf,vertex) * hr(ngr,ngs,kv,kf)
1603  ys(ngr,ngs) = ys(ngr,ngs) + zz(kf,vertex) * hs(ngr,ngs,kv,kf)
1604 
1605  enddo
1606  enddo
1607 
1608  xjac(ngr,ngs) = xr(ngr,ngs)*ys(ngr,ngs) - xs(ngr,ngs)*yr(ngr,ngs)
1609 
1610  enddo
1611  enddo
1612 
1613  psn(:,:) = (ps_axis - ps(:,:)) / ps_axis
1614 
1615  do ngr = 1, 4
1616  do ngs = 1, 4
1617 
1618  sum_vol = sum_vol + wgauss(ngr)*wgauss(ngs) * xjac(ngr,ngs) * xx(ngr,ngs)
1619  sum_area = sum_area + wgauss(ngr)*wgauss(ngs) * xjac(ngr,ngs)
1620 
1621  sum_p_area = sum_p_area + wgauss(ngr)*wgauss(ngs) * xjac(ngr,ngs) * pressure(psn(ngr,ngs))
1622  sum_p_vol = sum_p_vol + wgauss(ngr)*wgauss(ngs) * xjac(ngr,ngs) * xx(ngr,ngs) * pressure(psn(ngr,ngs))
1623 
1624  zjz = fdfdpsi(psn(ngr,ngs)) / (mu_zero * xx(ngr,ngs)) + dpdpsi(psn(ngr,ngs)) * xx(ngr,ngs)
1625 
1626  sum_c_area = sum_c_area + wgauss(ngr)*wgauss(ngs) * xjac(ngr,ngs) * zjz
1627 
1628  enddo
1629  enddo
1630 
1631 enddo
1632 
1633 volume = 2.e0_r8 * pi * sum_vol
1634 area = sum_area
1635 current = sum_c_area
1636 beta_p = 8.e0_r8 * pi / mu_zero * sum_p_area / (sum_c_area**2 )
1637 beta_t = 2.e0_r8 * mu_zero * sum_p_area / (sum_area * bgeo**2)
1638 beta_n = 100.e0_r8 * (4.e0_r8*pi/10.e0_r8) * beta_t / (mu_zero * abs(current) / (amin * bgeo))
1639 
1640 write(*,'(A,f16.8,A)') ' total volume : ',volume,' m^3'
1641 write(*,'(A,f16.8,A)') ' total area : ',area,' m^2'
1642 write(*,'(A,e12.4,A)') ' total current : ',current,' A'
1643 write(*,'(A,f16.8)') ' poloidal beta : ',beta_p
1644 write(*,'(A,f16.8)') ' toroidal beta : ',beta_t
1645 write(*,'(A,f16.8)') ' normalised beta : ',beta_n
1646 write(*,'(A,3f16.8)') ' magnetic axis : ',r_axis,z_axis,(r_axis-rgeo)/amin
1647 
1648 return
1649 end subroutine phys_values
1650 
1651 
1652 
1653 
1654 subroutine update_fdf(fmix,fdf_error)
1655 use helena_profiles
1656 use helena_axis
1657 use helena_constants
1658 use helena_surfaces
1659 use itm_types
1660 implicit none
1661 real (r8), allocatable :: r_av(:),or_av(:)
1662 !real (r8) :: current_profile, dpdpsi
1663 real (r8) :: psi_n, psi_n2, small, fdf_error, fdf_old, fmix
1664 integer :: n_int, i
1665 
1666 write(*,*) ' UPDATE FDF'
1667 
1668 n_psi = n_prof
1669 n_int = 5
1670 
1671 small = 1.d-8
1672 
1673 allocate(psi_values(n_psi),r_av(n_psi),or_av(n_psi))
1674 
1675 do i=1,n_prof
1676  psi_n = float(i-1)/float(n_prof-1)
1677  psi_values(i) = ps_axis - (1. - small) * psi_n * ps_axis
1678 enddo
1679 
1680 call find_flux_surfaces
1681 call fluxsurface_current(r_av, or_av)
1682 
1683 fdf_old = 0.e0_r8
1684 fdf_error = 0.e0_r8
1685 
1686 do i=1,n_prof
1687 
1688  psi_n = 1. - psi_values(i)/ps_axis
1689  psi_n2 = float(i-1)/float(n_prof-1)
1690 
1691  fdf_old = fdf_dpsi(i)
1692 
1693  fdf_dpsi(i) = mu_zero *(- current_profile(psi_n) - r_av(i) * dpdpsi(psi_n) ) / or_av(i)
1694 
1695  fdf_dpsi(i) = (1.-fmix)*fdf_dpsi(i) + fmix * fdf_old
1696 
1697 ! write(*,'(i4,8e12.4)') i,R_av,OR_av,fdf_dpsi(i),dp_dpsi(i),dpdpsi(psi_n),psi_n,psi_n2
1698 
1699  fdf_error= fdf_error + abs(fdf_old - fdf_dpsi(i))
1700 
1701 enddo
1702 
1703 fdf_error = fdf_error / float(n_prof)
1704 
1705 !call lplot6(2,1,psi_values,fdf_dpsi,n_prof,'fdf')
1706 
1707 deallocate(psi_values,r_av,or_av)
1708 
1709 return
1710 end subroutine update_fdf
1711 
1712 subroutine gs_solve(n_iter,rhs_only,solve_only,error_iteration,amix,ifail)
1713 use helena_axis
1714 use helena_grid
1715 use itm_types
1716 implicit none
1717 integer :: i, n_iter, ifail
1718 logical :: solve_only, rhs_only
1719 real (r8) :: error, error_iteration, amix, t_start, t_end
1720 
1721 ifail = 999
1722 
1723 call cpu_time(t_start)
1724 
1725 do i = 1, n_iter
1726 
1727  call findaxis
1728  call matrix_gs(ps_axis,rhs_only)
1729  call solve_matrix(amix,solve_only,error)
1730 
1731 ! write(*,'(A,i5,f12.8,e16.8)') ' GS_solve : ',i,R_axis,error
1732 
1733  if (error .lt. error_iteration) then
1734  write(*,'(A,i5,3e16.8)') ' GS_solve : ',i,r_axis,ps_axis,error
1735  ifail = 0
1736  exit
1737  endif
1738 
1739  solve_only = .true.
1740  rhs_only = .true.
1741 
1742 enddo
1743 
1744 call cpu_time(t_end)
1745 
1746 if (error .gt. error_iteration) then
1747  ifail = n_iter
1748  write(*,'(A,i5,3e16.8)') ' GS_solve failed : ',i,r_axis,ps_axis,error
1749 endif
1750 
1751 write(*,'(A,f12.8)') ' GS, CPU time : ',t_end-t_start
1752 
1753 return
1754 
1755 end subroutine gs_solve
1756 
1757 
1759 use helena_grid
1760 use helena_elements
1761 use helena_surfaces
1762 use helena_constants
1763 use itm_types
1764 implicit none
1765 real (r8) :: psimin, psimax, a0, a1, a2, a3
1766 real (r8) :: psi_test, dpsi_dr(4),dpsi_ds(4), drr_dr(4), drr_ds(4), dzz_dr(4), dzz_ds(4)
1767 real (r8) :: rr_psi(4), zz_psi(4), r_psi(4), s_psi(4), tht(4)
1768 real (r8) :: s, s2, s3, r_tmp, s_tmp, psr_tmp, pss_tmp, ttmp
1769 integer :: i, j, ifound, iv, im, is, n1, n2, n3
1770 integer :: ifail, itht(4), itmp
1771 
1772 
1773 write(*,*) ' find_flux_surfaces : ',n_psi
1774 
1775 if (.not. allocated(flux_surfaces)) allocate(flux_surfaces(n_psi))
1776 
1777 do j=1, n_psi
1778  flux_surfaces(j)%n_pieces = 0
1779  flux_surfaces(j)%elm = 0
1780  flux_surfaces(j)%r = 0
1781  flux_surfaces(j)%s = 0
1782 enddo
1783 
1784 do i=1, n_elms
1785 
1786  call psi_minmax(i,psimin,psimax)
1787 
1788  do j=1, n_psi
1789 
1790  ifound = 0
1791 
1792  if ((psi_values(j) .ge. psimin) .and. (psi_values(j) .le. psimax)) then
1793 
1794  do iv=1, 4
1795 
1796  im = mod(iv,4) + 1
1797  n1 = elm_list(iv,i)
1798  n2 = elm_list(im,i)
1799 
1800  is = mod(iv,2) + 2
1801 
1802  if (iv .gt. 2) then
1803  n3 = n2
1804  n2 = n1
1805  n1 = n3
1806  endif
1807 
1808  a3 = ( psi(1,n1) + psi(is,n1) - psi(1,n2) + psi(is,n2))/4.
1809  a2 = ( - psi(is,n1) + psi(is,n2))/4.
1810  a1 = (-3*psi(1,n1) - psi(is,n1) + 3*psi(1,n2) - psi(is,n2))/4.
1811  a0 = ( 2*psi(1,n1) + psi(is,n1) + 2*psi(1,n2) - psi(is,n2))/4. - psi_values(j)
1812 
1813  call solvp3(a0,a1,a2,a3,s,s2,s3,ifail)
1814 
1815  if (abs(s) .le. 1.) then
1816 
1817  ifound = ifound + 1
1818 
1819  call flux_surface_add_point(s,i,iv,ifound,r_psi,s_psi,dpsi_dr,dpsi_ds)
1820 
1821  endif
1822 
1823  if (abs(s2) .le. 1.) then
1824 
1825  ifound = ifound + 1
1826 
1827  call flux_surface_add_point(s2,i,iv,ifound,r_psi,s_psi,dpsi_dr,dpsi_ds)
1828 
1829  if (abs(s3) .le. 1.) write(*,*) ' another solution : ',s3
1830 
1831  endif
1832 
1833  enddo ! end of 4 edges
1834 
1835  if (ifound .eq. 2) then
1836 
1837  call flux_surface_add_line(i,j,r_psi(1:2),s_psi(1:2),dpsi_dr(1:2),dpsi_ds(1:2))
1838 
1839  elseif (ifound .eq. 4) then
1840 
1841 ! complicated : 2 line pieces but which point belongs to which line piece?
1842 
1843  tht(1:4) = atan2(s_psi(1:4),r_psi(1:4))
1844 
1845  where (tht .lt. 0.) tht = tht + 2.e0_r8*pi
1846 
1847  itht(1)= 1; itht(2) = 2; itht(3) = 3; itht(4) = 4
1848 
1849  if (tht(2) .lt. tht(1)) then
1850  itmp = itht(1); itht(1) = itht(2) ; itht(2) = itmp;
1851  endif
1852  if (tht(4) .lt. tht(3)) then
1853  itmp = itht(3); itht(3) = itht(4) ; itht(4) = itmp;
1854  endif
1855  if (tht(itht(3)) .lt. tht(itht(2))) then
1856  itmp = itht(2); itht(2) = itht(3) ; itht(3) = itmp;
1857  endif
1858  if (tht(itht(2)) .lt. tht(itht(1))) then
1859  itmp = itht(1); itht(1) = itht(2) ; itht(2) = itmp;
1860  endif
1861  if (tht(itht(4)) .lt. tht(itht(3))) then
1862  itmp = itht(3); itht(3) = itht(4) ; itht(4) = itmp;
1863  endif
1864  if (tht(itht(3)) .lt. tht(itht(2))) then
1865  itmp = itht(2); itht(2) = itht(3) ; itht(3) = itmp;
1866  endif
1867 
1868 ! write(*,*) i,j
1869 ! write(*,'(4f12.8)') tht
1870 ! write(*,'(4i5)') itht
1871 ! write(*,'(4f12.8)') tht(itht)
1872 ! write(*,'(4f12.8)') r_psi
1873 ! write(*,'(4f12.8)') s_psi
1874 ! write(*,'(4f12.8)') dpsi_dr
1875 ! write(*,'(4f12.8)') dpsi_ds
1876 
1877  call flux_surface_add_line(i,j,r_psi(itht(1:2)),s_psi(itht(1:2)),dpsi_dr(itht(1:2)),dpsi_ds(itht(1:2)))
1878  call flux_surface_add_line(i,j,r_psi(itht(3:4)),s_psi(itht(3:4)),dpsi_dr(itht(3:4)),dpsi_ds(itht(3:4)))
1879 
1880  endif
1881 
1882  endif
1883 
1884  enddo
1885 
1886 enddo
1887 
1888 return
1889 end subroutine find_flux_surfaces
1890 
1891 subroutine flux_surface_add_line(i,j,r_psi,s_psi,dpsi_dr,dpsi_ds)
1892 use helena_grid
1893 use helena_elements
1894 use helena_surfaces
1895 use itm_types
1896 implicit none
1897 integer :: i, j,node1, node2, node3, node4
1898 real (r8) :: psi_value, r_psi(*), s_psi(*), dpsi_dr(*), dpsi_ds(*)
1899 real (r8) :: rr1, rr2, ss1, ss2,sgn, drs, xl1 ,xl2, drr1, drr2, dss1, dss2, t
1900 real (r8) :: ri, si, dri, dsi, delta_ri, delta_si,psi_test, dummy_r, dummy_s, dl1, dl2
1901 
1902 rr1 = r_psi(1)
1903 rr2 = r_psi(2)
1904 ss1 = s_psi(1)
1905 ss2 = s_psi(2)
1906 
1907 sgn = 1.e0_r8
1908 
1909 if ((rr1 .eq. -1.e0_r8).and. (dpsi_ds(1).lt. 0.e0_r8)) then
1910  sgn = -1.e0_r8
1911 elseif ((rr1 .eq. +1.e0_r8).and. (dpsi_ds(1).gt. 0.e0_r8)) then
1912  sgn = -1.e0_r8
1913 endif
1914 if ((ss1 .eq. -1.e0_r8).and. (dpsi_dr(1).gt. 0.e0_r8)) then
1915  sgn = -1.e0_r8
1916 elseif ((ss1 .eq. +1.e0_r8).and. (dpsi_dr(1).lt. 0.e0_r8)) then
1917  sgn = -1.e0_r8
1918 endif
1919 
1920 drs = sgn * sqrt((rr2-rr1)**2 + (ss2-ss1)**2)
1921 
1922 xl1 = 0.5e0_r8 * drs / sqrt(dpsi_dr(1)**2 + dpsi_ds(1)**2) ! temporary fix; waiting for ideas
1923 xl2 = 0.5e0_r8 * drs / sqrt(dpsi_dr(2)**2 + dpsi_ds(2)**2)
1924 
1925 drr1 = xl1 * dpsi_ds(1)
1926 drr2 = xl2 * dpsi_ds(2)
1927 dss1 = - xl1 * dpsi_dr(1)
1928 dss2 = - xl2 * dpsi_dr(2)
1929 
1930 !------------------------------------------- attempt a correction step to correct drr1,drr2,dss1,dss2
1931 
1932 t = 0.e0_r8 ! make the curve fit exactly at t=0.
1933 
1934 call cub1d(rr1, drr1, rr2, drr2, t, ri, dri)
1935 call cub1d(ss1, dss1, ss2, dss2, t, si, dsi)
1936 
1937 node1 = elm_list(1,i); node2 = elm_list(2,i); node3 = elm_list(3,i); node4 = elm_list(4,i)
1938 
1939 call interp2(psi(:,node1),psi(:,node2),psi(:,node3),psi(:,node4),ri,si,psi_test,dummy_r,dummy_s)
1940 
1941 delta_ri = 0.5e0_r8 * (psi_values(j) - psi_test) / dummy_r
1942 delta_si = 0.5e0_r8 * (psi_values(j) - psi_test) / dummy_s
1943 
1944 call solvem2(0.25e0_r8*drr1,-0.25e0_r8*drr2,0.25e0_r8*dss1,-0.25e0_r8*dss2,delta_ri,delta_si,dl1,dl2)
1945 
1946 if ((abs(dl1) .lt. 0.1e0_r8) .and. (abs(dl2).lt.0.1e0_r8)) then
1947 
1948  drr1 = (1.e0_r8+ dl1) * drr1
1949  dss1 = (1.e0_r8+ dl1) * dss1
1950  drr2 = (1.e0_r8+ dl2) * drr2
1951  dss2 = (1.e0_r8+ dl2) * dss2
1952 
1953 endif
1954 
1955 flux_surfaces(j)%n_pieces = flux_surfaces(j)%n_pieces + 1
1956 flux_surfaces(j)%elm(flux_surfaces(j)%n_pieces) = i
1957 flux_surfaces(j)%r(1:4,flux_surfaces(j)%n_pieces) = (/ rr1, drr1, rr2, drr2 /)
1958 flux_surfaces(j)%s(1:4,flux_surfaces(j)%n_pieces) = (/ ss1, dss1, ss2, dss2 /)
1959 
1960 return
1961 end subroutine flux_surface_add_line
1962 
1963 subroutine flux_surface_add_point(s,i,iv,ifound,r_psi,s_psi,dpsi_dr,dpsi_ds)
1964 
1965 use helena_elements
1966 use helena_grid
1967 use itm_types
1968 implicit none
1969 
1970 integer :: i, iv, ifound, node1, node2, node3, node4
1971 real (r8) :: s, r_psi(*), s_psi(*), dpsi_dr(*), dpsi_ds(*), psi_test
1972 
1973 if (iv .eq. 1) then
1974  r_psi(ifound) = -1.e0_r8 ; s_psi(ifound) = s
1975 elseif (iv .eq. 2) then
1976  r_psi(ifound) = s ; s_psi(ifound) = 1.e0_r8
1977 elseif (iv .eq. 3) then
1978  r_psi(ifound) = +1.e0_r8 ; s_psi(ifound) = s
1979 elseif (iv .eq. 4) then
1980  r_psi(ifound) = s ; s_psi(ifound) = -1.e0_r8
1981 endif
1982 
1983 node1 = elm_list(1,i); node2 = elm_list(2,i); node3 = elm_list(3,i); node4 = elm_list(4,i)
1984 
1985 call interp2(psi(:,node1),psi(:,node2),psi(:,node3),psi(:,node4), &
1986  r_psi(ifound),s_psi(ifound),psi_test,dpsi_dr(ifound),dpsi_ds(ifound))
1987 
1988 return
1989 end subroutine flux_surface_add_point
1990 
1992 use helena_surfaces
1993 use helena_elements
1994 use helena_grid
1995 use itm_types
1996 implicit none
1997 integer :: j, k,ip, nplot, node1, node2, node3, node4, i_elm
1998 real (r8) :: t, rr1, rr2, drr1, drr2, ss1, ss2, dss1, dss2, ri, si, dri, dsi, dummy1, dummy2
1999 real (r8),allocatable :: rplot(:), zplot(:)
2000 character*13 :: label
2001 
2002 nplot=5
2003 allocate(rplot(nplot),zplot(nplot))
2004 
2005 label= 'Flux surfaces'
2006 
2007 if (((z_max-z_min)/(r_max-r_min)) .lt. 1.5e0_r8 ) then
2008  CALL nframe(2,21,1,r_min,r_max,z_min,z_max,label,13,'R [m]',5,'Z [m]',5)
2009 else
2010  CALL nframe(22,1,1,r_min,r_max,z_min,z_max,label,13,'R [m]',5,'Z [m]',5)
2011 endif
2012 
2013 !call plot_elements
2014 
2015 do j=1,n_psi
2016 
2017  do k=1,flux_surfaces(j)%n_pieces
2018 
2019  i_elm = flux_surfaces(j)%elm(k)
2020 
2021  node1 = elm_list(1,i_elm)
2022  node2 = elm_list(2,i_elm)
2023  node3 = elm_list(3,i_elm)
2024  node4 = elm_list(4,i_elm)
2025 
2026  rr1 = flux_surfaces(j)%r(1,k)
2027  drr1 = flux_surfaces(j)%r(2,k)
2028  rr2 = flux_surfaces(j)%r(3,k)
2029  drr2 = flux_surfaces(j)%r(4,k)
2030 
2031  ss1 = flux_surfaces(j)%s(1,k)
2032  dss1 = flux_surfaces(j)%s(2,k)
2033  ss2 = flux_surfaces(j)%s(3,k)
2034  dss2 = flux_surfaces(j)%s(4,k)
2035 
2036  do ip = 1, nplot
2037 
2038  t = -1. + 2.*float(ip-1)/float(nplot-1)
2039 
2040  call cub1d(rr1, drr1, rr2, drr2, t, ri, dri)
2041  call cub1d(ss1, dss1, ss2, dss2, t, si, dsi)
2042 
2043  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),ri,si,rplot(ip),dummy1,dummy2)
2044  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),ri,si,zplot(ip),dummy1,dummy2)
2045 
2046  enddo
2047 
2048  call lincol(1)
2049  if (k .gt. 1) then
2050  if (i_elm .eq. flux_surfaces(j)%elm(k-1)) then
2051  call lincol(2)
2052  write(51,*) ' 1 setlinewidth '
2053  elseif (i_elm .eq. flux_surfaces(j)%elm(k+1)) then
2054  call lincol(3)
2055  write(51,*) ' 2 setlinewidth '
2056  else
2057  call lincol(1)
2058  write(51,*) ' .5 setlinewidth '
2059  endif
2060  endif
2061 
2062  call lplot6(22,1,rplot,zplot,-nplot,' ')
2063 
2064  enddo
2065 
2066 enddo
2067 
2068 return
2069 end subroutine plot_flux_surfaces
2070 
2071 subroutine fluxsurface_current(R_av, OR_av)
2072 use helena_grid
2073 use helena_elements
2074 use helena_axis
2075 use helena_surfaces
2076 use helena_constants
2077 use helena_gauss_4
2078 use itm_types
2079 implicit none
2080 real (r8) :: r_av(*), or_av(*), sum_dl, sum_rav, sum_orav
2081 integer :: i_elm, j, k, n1, n2, n3, node1, node2, node3, node4
2082 real (r8) :: t,rr1, rr2, drr1, drr2, ss1, ss2, dss1, dss2, ri, si, dri, dsi, dl
2083 real (r8) :: rrgi, drrgi_dr, drrgi_ds, zzgi, dzzgi_dr, dzzgi_ds, drrgi_dt, dzzgi_dt
2084 real (r8) :: psgi, dpsgi_dr, dpsgi_ds, psi_r, psi_z, rzjac, grad_psi
2085 integer :: ig, ip
2086 
2087 
2088 do j=1, n_psi
2089 
2090  sum_dl = 0.e0_r8
2091  sum_rav = 0.e0_r8
2092  sum_orav = 0.e0_r8
2093 
2094  do k=1, flux_surfaces(j)%n_pieces
2095 
2096  do ig = 1, 4
2097 
2098  t = xgauss(ig)
2099 
2100  rr1 = flux_surfaces(j)%r(1,k)
2101  drr1 = flux_surfaces(j)%r(2,k)
2102  rr2 = flux_surfaces(j)%r(3,k)
2103  drr2 = flux_surfaces(j)%r(4,k)
2104 
2105  ss1 = flux_surfaces(j)%s(1,k)
2106  dss1 = flux_surfaces(j)%s(2,k)
2107  ss2 = flux_surfaces(j)%s(3,k)
2108  dss2 = flux_surfaces(j)%s(4,k)
2109 
2110  call cub1d(rr1, drr1, rr2, drr2, t, ri, dri)
2111  call cub1d(ss1, dss1, ss2, dss2, t, si, dsi)
2112 
2113  i_elm = flux_surfaces(j)%elm(k)
2114 
2115  node1 = elm_list(1,i_elm)
2116  node2 = elm_list(2,i_elm)
2117  node3 = elm_list(3,i_elm)
2118  node4 = elm_list(4,i_elm)
2119 
2120 !-----------------------------------------------------------
2121  call interp2(psi(:,node1),psi(:,node2),psi(:,node3),psi(:,node4),ri,si,psgi,dpsgi_dr,dpsgi_ds)
2122  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),ri,si,rrgi,drrgi_dr,drrgi_ds)
2123  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),ri,si,zzgi,dzzgi_dr,dzzgi_ds)
2124 
2125  drrgi_dt = drrgi_dr * dri + drrgi_ds * dsi
2126  dzzgi_dt = dzzgi_dr * dri + dzzgi_ds * dsi
2127 
2128  dl = sqrt(drrgi_dt**2 + dzzgi_dt**2)
2129 
2130  rzjac = drrgi_dr * dzzgi_ds - drrgi_ds * dzzgi_dr
2131 
2132  psi_r = ( dpsgi_dr * dzzgi_ds - dpsgi_ds * dzzgi_dr ) / rzjac
2133  psi_z = ( - dpsgi_dr * drrgi_ds + dpsgi_ds * drrgi_dr ) / rzjac
2134 
2135  grad_psi = sqrt(psi_r * psi_r + psi_z * psi_z)
2136 !----------------------------------------------------------
2137 
2138  sum_dl = sum_dl + wgauss(ig) * dl * rrgi / grad_psi
2139  sum_rav = sum_rav + wgauss(ig) * rrgi * dl * rrgi / grad_psi
2140  sum_orav = sum_orav + wgauss(ig) / rrgi * dl * rrgi / grad_psi
2141 
2142  enddo
2143 
2144  enddo
2145 
2146  r_av(j) = sum_rav / sum_dl
2147  or_av(j) = sum_orav / sum_dl
2148 
2149 enddo
2150 
2151 r_av(1) = r_axis
2152 or_av(1) = 1.e0_r8/ r_axis
2153 
2154 return
2155 end subroutine fluxsurface_current
2156 
2157 subroutine fluxsurface_integrals(powers,n_int,n_var,results)
2158 !----------------------------------------------------------------------
2159 ! subroutine calculats arbitrary flux surfcae quantities as defined by
2160 ! the matrix powers. The entries in the matrix define the power of
2161 ! the variables in the integrals
2162 !
2163 ! powers(n_int,n_var)
2164 ! n_int : the number of flux surface quantities
2165 ! n_var : the number of variables in the integrand
2166 !
2167 ! nvar = 1: R 2: B^2 3: grad(psi)
2168 !---------------------------------------------------------------------
2169 use helena_grid
2170 use helena_elements
2171 use helena_axis
2172 use helena_surfaces
2173 use helena_constants
2174 use helena_gauss_4
2175 use itm_types
2176 implicit none
2177 integer :: n_int,n_var
2178 real (r8) :: powers(n_var,n_int), results(n_psi+1,n_int)
2179 integer :: i_elm, j, k, n1, n2, n3, node1, node2, node3, node4
2180 real (r8) :: t,rr1, rr2, drr1, drr2, ss1, ss2, dss1, dss2, ri, si, dri, dsi, dl
2181 real (r8) :: rrgi, drrgi_dr, drrgi_ds, zzgi, dzzgi_dr, dzzgi_ds, drrgi_dt, dzzgi_dt
2182 real (r8) :: psgi, dpsgi_dr, dpsgi_ds, psi_r, psi_z, rzjac, grad_psi, psi_n
2183 real (r8) :: sum_dl, b_tot2
2184 integer :: i,m, ig, ip
2185 !real (r8) :: fdia
2186 
2187 write(*,*) ' flux_surface_integrals : ',n_psi,n_int,n_var
2188 
2189 results(1:n_psi+1,1:n_int) = 0.e0_r8
2190 
2191 do i=1, n_psi
2192 
2193  psi_n = 1.e0_r8 - psi_values(i)/ps_axis
2194 
2195  sum_dl = 0.e0_r8
2196 
2197  do k=1, flux_surfaces(i)%n_pieces
2198 
2199  do ig = 1, 4
2200 
2201  t = xgauss(ig)
2202 
2203  rr1 = flux_surfaces(i)%r(1,k)
2204  drr1 = flux_surfaces(i)%r(2,k)
2205  rr2 = flux_surfaces(i)%r(3,k)
2206  drr2 = flux_surfaces(i)%r(4,k)
2207 
2208  ss1 = flux_surfaces(i)%s(1,k)
2209  dss1 = flux_surfaces(i)%s(2,k)
2210  ss2 = flux_surfaces(i)%s(3,k)
2211  dss2 = flux_surfaces(i)%s(4,k)
2212 
2213  call cub1d(rr1, drr1, rr2, drr2, t, ri, dri)
2214  call cub1d(ss1, dss1, ss2, dss2, t, si, dsi)
2215 
2216  i_elm = flux_surfaces(i)%elm(k)
2217 
2218  node1 = elm_list(1,i_elm)
2219  node2 = elm_list(2,i_elm)
2220  node3 = elm_list(3,i_elm)
2221  node4 = elm_list(4,i_elm)
2222 
2223  call interp2(psi(:,node1),psi(:,node2),psi(:,node3),psi(:,node4),ri,si,psgi,dpsgi_dr,dpsgi_ds)
2224  call interp2(rr(:,node1),rr(:,node2),rr(:,node3),rr(:,node4),ri,si,rrgi,drrgi_dr,drrgi_ds)
2225  call interp2(zz(:,node1),zz(:,node2),zz(:,node3),zz(:,node4),ri,si,zzgi,dzzgi_dr,dzzgi_ds)
2226 
2227  drrgi_dt = drrgi_dr * dri + drrgi_ds * dsi
2228  dzzgi_dt = dzzgi_dr * dri + dzzgi_ds * dsi
2229 
2230  dl = sqrt(drrgi_dt**2 + dzzgi_dt**2)
2231 
2232  rzjac = drrgi_dr * dzzgi_ds - drrgi_ds * dzzgi_dr
2233 
2234  psi_r = ( dpsgi_dr * dzzgi_ds - dpsgi_ds * dzzgi_dr ) / rzjac
2235  psi_z = ( - dpsgi_dr * drrgi_ds + dpsgi_ds * drrgi_dr ) / rzjac
2236 
2237  grad_psi = sqrt(psi_r * psi_r + psi_z * psi_z)
2238 
2239  b_tot2 = (fdia(psi_n) / rrgi)**2 + (grad_psi/ rrgi)**2
2240 
2241  sum_dl = sum_dl + wgauss(ig) * dl
2242 
2243  do m = 1, n_int
2244  results(i+1,m) = results(i+1,m) + wgauss(ig) * dl &
2245  * rrgi**powers(1,m) &
2246  * b_tot2**powers(2,m) &
2247  * grad_psi**powers(3,m)
2248 
2249  enddo
2250 
2251  enddo
2252 
2253  enddo
2254 
2255 ! results(i+1,1:n_int) = results(i+1,1:n_int) / sum_dl
2256 
2257 enddo
2258 
2259 !----------------------------------- values on axis
2260 
2261 do m=1, n_int
2262 
2263  results(1,m) = r_axis**powers(1,m) * b_axis**powers(2,m)
2264 
2265  if (powers(3,m) .eq. -1.e0_r8) then
2266  results(1,m) = results(1,m) * pi / sqrt(crr_axis*czz_axis)
2267  elseif (powers(3,m) .gt. 0.e0_r8) then
2268  results(1,m) = 0.e0_r8
2269  endif
2270 
2271 enddo
2272 
2273 return
2274 end subroutine fluxsurface_integrals
2275 
2276 subroutine helena_flux_surface_integrals(nr_flux,np_flux,RR_flux,ZZ_flux,PS_flux, &
2277  powers,n_int,n_var,results,q, vprime)
2278 !----------------------------------------------------------------------
2279 ! subroutine calculats arbitrary flux surfcae quantities as defined by
2280 ! the matrix powers. The entries in the matrix define the power of
2281 ! the variables in the integrals
2282 !
2283 ! requires fluxsurface aligned mesh
2284 !
2285 ! powers(n_int,n_var)
2286 ! n_int : the number of flux surface quantities
2287 ! n_var : the number of variables in the integrand
2288 !
2289 ! nvar = 1: R 2: B^2 3: grad(psi)
2290 !---------------------------------------------------------------------
2291 use helena_grid
2292 use helena_elements
2293 use helena_axis
2294 use helena_surfaces
2295 use helena_constants
2296 use helena_gauss_4
2297 use itm_types
2298 implicit none
2299 real (r8) :: rr_flux(4,*),zz_flux(4,*),ps_flux(4,*)
2300 integer :: n_int,n_var, nr_flux, np_flux
2301 real (r8) :: powers(n_var,n_int), results(nr_flux,n_int), q(nr_flux), vprime(nr_flux)
2302 integer :: i, j, k, m, n1, n2, n3, n4, ngs
2303 real (r8) :: rrg1, drrg1_dr, drrg1_ds, zzg1, dzzg1_dr, dzzg1_ds, drrg1_dt, dzzg1_dt
2304 real (r8) :: psg1, dpsg1_dr, dpsg1_ds, psi_r, psi_z, rzjac, grad_psi, ws
2305 real (r8) :: r, s, dl, sum_dl, b_tot2, bphi, grad_psi2, zjdchi, psi_n
2306 !real (r8) :: fdia
2307 
2308 write(*,*) ' flux_surface_integrals : ',n_psi,n_int,n_var
2309 write(*,*) ' nr_flux : ',nr_flux
2310 
2311 if (nr_flux .ne. n_psi+1) write(*,*) ' MAJOR PORBLEM in helena_fluxsurface_integral',nr_flux,n_psi
2312 
2313 
2314 results(1:n_psi+1,1:n_int) = 0.e0_r8
2315 q = 0.e0_r8
2316 vprime = 0.e0_r8
2317 
2318 r = + 1.e0_r8
2319 
2320 do i=1, nr_flux-1
2321 
2322  sum_dl = 0.e0_r8
2323 
2324  do j=1, np_flux
2325 
2326  n1 = (i-1)*np_flux + j
2327  n2 = (i-1)*np_flux + j + 1
2328  n3 = (i )*np_flux + j + 1
2329  n4 = (i )*np_flux + j
2330 
2331  if (j .eq. np_flux) then
2332  n1 = (i )*np_flux
2333  n2 = (i )*np_flux - np_flux + 1
2334  n3 = (i )*np_flux + 1
2335  n4 = (i )*np_flux + np_flux
2336  endif
2337 
2338 !------------------------------------- 4 POINT GAUSSIAN INT. IN S -----
2339  do ngs = 1, 4
2340 
2341  s = xgauss(ngs)
2342  ws = wgauss(ngs)
2343 
2344  call interp2(rr_flux(1,n1),rr_flux(1,n2),rr_flux(1,n3),rr_flux(1,n4),r,s,rrg1,drrg1_dr,drrg1_ds)
2345  call interp2(zz_flux(1,n1),zz_flux(1,n2),zz_flux(1,n3),zz_flux(1,n4),r,s,zzg1,dzzg1_dr,dzzg1_ds)
2346  call interp2(ps_flux(1,n1),ps_flux(1,n2),ps_flux(1,n3),ps_flux(1,n4),r,s,psg1,dpsg1_dr,dpsg1_ds)
2347 
2348  rzjac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
2349 
2350  dl = sqrt(drrg1_ds**2 + dzzg1_ds**2)
2351 
2352  if(rzjac .eq. 0.0_r8) then
2353  write(*,*) 'Warning: RZjac == 0, grad_psi2 set to 0.0'
2354  grad_psi2= 0.0_r8 ! DPC
2355  else
2356  grad_psi2= dpsg1_dr**2 * (drrg1_ds**2 + dzzg1_ds**2) / rzjac**2
2357  endif
2358 
2359  if(dpsg1_dr .eq. 0.0_r8) then
2360  write(*,*) 'Warning: dPSg1_dr == 0, ZJDCHI set to 0.0'
2361  zjdchi = 0.0_r8 ! DPC
2362  else
2363  zjdchi = 2.e0_r8 * pi * rrg1 * rzjac / dabs(dpsg1_dr)
2364  endif
2365 
2366  psi_n = - (psg1 - ps_axis) / ps_axis
2367 
2368  bphi = fdia(psi_n) / rrg1
2369 
2370  b_tot2 = bphi**2 + grad_psi2/rrg1**2
2371 
2372  sum_dl = sum_dl + ws * dl
2373 
2374  q(i+1) = q(i+1) + ws / (rrg1 * sqrt(grad_psi2)) * dl
2375  vprime(i+1) = vprime(i+1) + ws * zjdchi
2376 
2377 ! write(*,'(A,6i5,12f12.8)') ' test : ',i,j,n1,n2,n3,n4,r,s,PSg1,RRg1,RR_flux(1,N1),RR_flux(1,N2),RR_flux(1,N3),RR_flux(1,N4)
2378 
2379  do m = 1, n_int
2380 
2381 ! results(i+1,m) = results(i+1,m) + ws * dl &
2382 ! * RRg1**powers(1,m) &
2383 ! * B_tot2**powers(2,m) &
2384 ! * sqrt(grad_psi2)**powers(3,m)
2385 
2386  results(i+1,m) = results(i+1,m) + ws * zjdchi &
2387  * rrg1**powers(1,m) &
2388  * b_tot2**powers(2,m) &
2389  * sqrt(grad_psi2)**powers(3,m)
2390 
2391  enddo
2392 
2393  enddo
2394 
2395  enddo
2396 
2397  results(i+1,1:n_int) = results(i+1,1:n_int) / vprime(i+1)
2398 
2399 enddo
2400 
2401 !----------------------------------- values on axis
2402 q(1) = pi / (r_axis * sqrt(crr_axis*czz_axis))
2403 
2404 do m=1, n_int
2405 
2406  results(1,m) = r_axis**powers(1,m) * b_axis**powers(2,m)
2407 
2408  if (powers(3,m) .eq. -1.e0_r8) then
2409  results(1,m) = results(1,m) * pi / sqrt(crr_axis*czz_axis)
2410  elseif (powers(3,m) .gt. 0.e0_r8) then
2411  results(1,m) = 0.e0_r8
2412  endif
2413 enddo
2414 
2415 return
2416 end subroutine helena_flux_surface_integrals
2417 
2418 subroutine solvem2(a,b,c,d,e,f,x,y)
2419 !-----------------------------------------------------------------------
2420 ! solves a 2x2 set of equations
2421 !-----------------------------------------------------------------------
2422 use itm_types
2423 implicit none
2424 real (r8) :: a,b,c,d,e,f,x,y, det
2425 
2426 det = a*d - b*c
2427 
2428 if (det .ne. 0.e0_r8) then
2429  x = ( d * e - b * f ) / det
2430  y = ( - c * e + a * f ) / det
2431 else
2432  x = 0.e0_r8
2433  y = 0.e0_r8
2434 endif
2435 
2436 return
2437 end subroutine solvem2
2438 
2439 SUBROUTINE solvp3(C0,C1,C2,C3,X1,X2,X3,IFAIL)
2440 !-----------------------------------------------------------------------
2441 ! SOLVES A CUBIC EQUATION WITH A SOLUTION WITH -1.< X < 1
2442 ! CN : THE COEFFICIENT OF X**N, X : THE REAL SOLUTION WITH -1.< X < 1.
2443 !-----------------------------------------------------------------------
2444 use itm_types
2445 implicit none
2446 real (r8) :: c0, c1, c2, c3, x1, x2, x3, dum, tol, angle
2447 real (r8) :: a0, a1, a2, aa, bb, cc, det, pi, p, q, u, v
2448 integer :: ifail
2449 
2450 x1 = 99.e0_r8
2451 x2 = 999.e0_r8
2452 x3 = 9999.e0_r8
2453 tol = 0.
2454 ifail = 0
2455 
2456 !------------------------------------- 2nd order poly for small c3
2457 IF (abs(c3)/(abs(c1)+abs(c2)+abs(c3)) .LT. 1.d-9) THEN
2458  aa = c2
2459  bb = c1
2460  cc = c0
2461  det = bb**2 - 4*aa*cc
2462  IF (det.GE.0.) THEN
2463  x1 = root(aa,bb,cc,det,1.e0_r8)
2464  IF (abs(x1).GT. 1.e0_r8 + tol) THEN
2465  x1 = root(aa,bb,cc,det,-1.e0_r8)
2466  ENDIF
2467  ELSE
2468  ifail = 1
2469  ENDIF
2470 
2471 ELSE
2472 !------------------------------------- 3rd order poly solution
2473  pi = 2*asin(1.e0_r8)
2474  a0 = c0 / c3
2475  a1 = c1 / c3
2476  a2 = c2 / c3
2477  p = - (a2**2)/3.e0_r8 + a1
2478  q = 2.e0_r8/27.e0_r8*(a2**3) - a2 * a1/3.e0_r8 + a0
2479  det = (p/3.e0_r8)**3 + (q/2.e0_r8)**2
2480  IF (det .GE. 0) THEN
2481  u = sign(1.e0_r8,-q/2.e0_r8+sqrt(det))*abs(-q/2.e0_r8 + sqrt(det))**(1.e0_r8/3.e0_r8)
2482  v = sign(1.e0_r8,-q/2.e0_r8-sqrt(det))*abs(-q/2.e0_r8 - sqrt(det))**(1.e0_r8/3.e0_r8)
2483  x1 = u + v - a2/3.e0_r8
2484  IF (abs(x1) .GE. (1.e0_r8+tol)) ifail = 1
2485  ELSE
2486  p = -p
2487  angle = sign(1.e0_r8,p)*acos((q/2.e0_r8)/sqrt(abs(p)/3.e0_r8)**3)
2488  x1 = -2.e0_r8*sqrt(abs(p)/3.e0_r8)*cos(angle/3.e0_r8) - a2/3.e0_r8
2489  x2 = -2.e0_r8*sqrt(abs(p)/3.e0_r8)*cos(2*pi/3.e0_r8 - angle/3.e0_r8) - a2/3.e0_r8
2490  x3 = -2.e0_r8*sqrt(abs(p)/3.e0_r8)*cos(2*pi/3.e0_r8 + angle/3.e0_r8) - a2/3.e0_r8
2491  ENDIF
2492  IF (abs(x1) .GT. abs(x2)) THEN
2493  dum = x1
2494  x1 = x2
2495  x2 = dum
2496  ENDIF
2497  IF (abs(x2) .GT. abs(x3)) THEN
2498  dum = x2
2499  x2 = x3
2500  x3 = dum
2501  ENDIF
2502  IF (abs(x1) .GT. abs(x2)) THEN
2503  dum = x1
2504  x1 = x2
2505  x2 = dum
2506  ENDIF
2507 ENDIF
2508 IF (abs(x1) .GT. (1.e0_r8 + tol)) ifail=1
2509 
2510 RETURN
2511 END SUBROUTINE solvp3
2512 
2513 FUNCTION root(A,B,C,D,SGN)
2514 !---------------------------------------------------------------------
2515 ! THIS FUNCTION GIVES BETTER ROOTS OF QUADRATICS BY AVOIDING
2516 ! CANCELLATION OF SMALLER ROOT
2517 !---------------------------------------------------------------------
2518 use itm_types
2519 implicit none
2520 real (r8) :: root,a, b, c, d, sgn
2521 
2522 IF (b*sgn .GE. 0.e0_r8) THEN
2523  root = -2.e0_r8*c/(b+sgn*sqrt(d))
2524 ELSE
2525  root = (-b + sgn*sqrt(d)) / (2.e0_r8 * a)
2526 ENDIF
2527 RETURN
2528 END FUNCTION root
2529 
2530 
2531 subroutine psi_minmax(n,psimin,psimax)
2532 use helena_grid
2533 use helena_elements
2534 use itm_types
2535 implicit none
2536 real (r8) :: psimin, psimax, psma, psmi, psmima, psim, psimr, psip, psipr
2537 real (r8) :: aa, bb, cc, det, r, dummy
2538 integer :: i, n, im, n1, n2
2539 
2540 psimin = 1d10
2541 psimax =-1d10
2542 
2543 do i=1, 4
2544 
2545  im = mod(i,4) + 1
2546  n1 = elm_list(i,n)
2547  n2 = elm_list(im,n)
2548 
2549  IF (i .eq. 1) THEN
2550  psim = psi(1,n1)
2551  psimr = psi(3,n1)
2552  psip = psi(1,n2)
2553  psipr = psi(3,n2)
2554  ELSEif (i .eq. 2) then
2555  psim = psi(1,n1)
2556  psimr = psi(2,n1)
2557  psip = psi(1,n2)
2558  psipr = psi(2,n2)
2559  ELSEIF (i .eq. 3) then
2560  psim = psi(1,n1)
2561  psimr = - psi(3,n1)
2562  psip = psi(1,n2)
2563  psipr = - psi(3,n2)
2564  ELSEIF (i .eq. 4) then
2565  psim = psi(1,n1)
2566  psimr = - psi(2,n1)
2567  psip = psi(1,n2)
2568  psipr = - psi(2,n2)
2569  ENDIF
2570 
2571  psma = max(psim,psip)
2572  psmi = min(psim,psip)
2573  aa = 3.e0_r8 * (psim + psimr - psip + psipr ) / 4.e0_r8
2574  bb = ( - psimr + psipr ) / 2.e0_r8
2575  cc = ( - 3*psim - psimr + 3*psip - psipr) / 4.e0_r8
2576  det = bb**2 - 4*aa*cc
2577  IF (det .GE. 0.e0_r8) THEN
2578  r = (-bb + sqrt(bb**2-4*aa*cc) ) / (2*aa)
2579  IF (abs(r) .GT. 1.e0_r8) THEN
2580  r = (-bb - sqrt(bb**2-4*aa*cc) ) / (2*aa)
2581  ENDIF
2582  IF (abs(r) .LE. 1.e0_r8) THEN
2583  CALL cub1d(psim,psimr,psip,psipr,r,psmima,dummy)
2584  psma = max(psma,psmima)
2585  psmi = min(psmi,psmima)
2586  ENDIF
2587  ENDIF
2588  psimin = min(psimin,psmi)
2589  psimax = max(psimax,psma)
2590 ENDDO
2591 
2592 RETURN
2593 END subroutine psi_minmax
2594 
2595 SUBROUTINE tht_minmax(n,thtmin,thtmax)
2596 use helena_grid
2597 use helena_elements
2598 use helena_axis
2599 use helena_constants
2600 use itm_types
2601 implicit none
2602 real (r8) :: thtmin, thtmax, theta
2603 integer :: i, node, n
2604 
2605 thtmin = 1d10
2606 thtmax =-1d10
2607 
2608 do i=1,4
2609  node = elm_list(i,n)
2610  theta = atan2(zz(1,node)-z_axis,rr(1,node)-r_axis)
2611  if (theta .lt. 0.) then
2612  theta = theta + 2.e0_r8*pi
2613  endif
2614  thtmin = min(theta,thtmin)
2615  thtmax = max(theta,thtmax)
2616 enddo
2617 
2618 return
2619 end SUBROUTINE tht_minmax
2620 
2621 subroutine initialise_profiles(n_prof_in,iopt_p,iopt_f,psi_in, pprime_in, ffprime_in,pressure_in, fdia_in, current_in)
2622 !-------------------------------------------------------------------------------
2623 ! initialising the profiles contained in helena_profiles
2624 !
2625 ! iopt_p = 1 : use pressure and psi profile
2626 ! iopt_p = 2 : use pprime profile
2627 !
2628 ! iopt_f = 1 : use f_dia and psi profile
2629 ! iopt_f = 2 : use ffprime profile
2630 ! iopt_f = 3 : use current profile and ffprime profile
2631 ! iopt_f = 4 : use current profile and reinitialise ffprime
2632 !-------------------------------------------------------------------------------
2633 use helena_profiles
2634 use helena_boundary
2635 use helena_axis
2636 use helena_constants
2637 use itm_types
2638 implicit none
2639 real (r8) :: psi, dpsi, sump, sumf, f0, f_old, f_tmp
2640 real (r8),allocatable :: psi_norm(:), psi_prof(:), sp1(:) ,sp2(:), sp3(:), sp4(:)
2641 real (r8) :: pprime_in(*), ffprime_in(*), pressure_in(*), fdia_in(*), current_in(*), psi_in(*)
2642 integer :: i, n_prof_in, iopt_p, iopt_f
2643 real (r8) :: abltg(3), p_tmp, si, rbnd_av, orbnd_av, r_av, or_av, ps0, ps1
2644 !real (r8) :: spwert
2645 
2646 write(*,'(A)') ' **************************************'
2647 write(*,'(A,i7,A)') ' * initialising profiles',n_prof_in,' *'
2648 write(*,'(A)') ' **************************************'
2649 
2650 ps0 = psi_in(1)
2651 ps1 = psi_in(n_prof_in)
2652 ps_axis = abs(ps1 - ps0)
2653 
2654 p_bnd = pressure_in(n_prof_in)
2655 
2656 allocate(psi_norm(n_prof_in))
2657 
2658 do i=1,n_prof_in
2659  psi_norm(i) = (psi_in(i)- ps0)/(ps1 - ps0)
2660 ! write(*,'(i5,8e12.4)') i,psi_in(i),psi_norm(i),pprime_in(i),ffprime_in(i),pressure_in(i),fdia_in(i),current_in(i)
2661 enddo
2662 
2663 allocate(sp1(n_prof_in),sp2(n_prof_in),sp3(n_prof_in),sp4(n_prof_in))
2664 
2665 n_prof = 101
2666 allocate(psi_prof(n_prof), dp_dpsi(n_prof), zjz_psi(n_prof), fdf_dpsi(n_prof))
2667 
2668 if (iopt_p .eq. 1) then ! calculate pprime from pressure profile
2669 
2670  write(*,*) ' HELENA : using pressure profile as input'
2671 
2672  call spline(n_prof_in,psi_norm,pressure_in,0.e0_r8,0.e0_r8,2,sp1,sp2,sp3,sp4)
2673 
2674  do i = 1, n_prof
2675 
2676  psi_prof(i) = float(i-1)/float(n_prof-1)
2677 
2678  p_tmp = spwert(n_prof_in,psi_prof(i),sp1,sp2,sp3,sp4,psi_norm,abltg)
2679 
2680  dp_dpsi(i) = abltg(1) / abs(ps_axis)
2681 
2682  enddo
2683 
2684  dp_dpsi(1) = dp_dpsi(3)
2685  dp_dpsi(2) = dp_dpsi(3)
2686 
2687 else
2688 
2689  write(*,*) ' HELENA : using pprime profile as input'
2690 
2691  call spline(n_prof_in,psi_norm,pprime_in,0.e0_r8,0.e0_r8,2,sp1,sp2,sp3,sp4)
2692 
2693  do i = 1, n_prof
2694 
2695  psi_prof(i) = float(i-1)/float(n_prof-1)
2696 
2697  dp_dpsi(i) = spwert(n_prof_in,psi_prof(i),sp1,sp2,sp3,sp4,psi_norm,abltg)
2698 
2699  enddo
2700 
2701 endif
2702 
2703 if (iopt_f .eq. 1) then ! calculate ffprime from fdia profile
2704 
2705  write(*,*) ' HELENA : using fdia profile as input'
2706 
2707  call spline(n_prof_in,psi_norm,fdia_in,0.0_r8,0.0_r8,2,sp1,sp2,sp3,sp4)
2708 
2709  do i = 1, n_prof
2710 
2711  psi_prof(i) = float(i-1)/float(n_prof-1)
2712 
2713  f_tmp = spwert(n_prof_in,psi_prof(i),sp1,sp2,sp3,sp4,psi_norm,abltg)
2714 
2715  fdf_dpsi(i) = f_tmp * abltg(1) / abs(ps_axis)
2716 
2717  enddo
2718 
2719  fdf_dpsi(1) = fdf_dpsi(3)
2720  fdf_dpsi(2) = fdf_dpsi(3)
2721 
2722 elseif ((iopt_f .eq. 2) .or. (iopt_f .eq. 3)) then
2723 
2724  write(*,*) ' HELENA : using ffprime profile as input'
2725 
2726  call spline(n_prof_in,psi_norm,ffprime_in,0.e0_r8,0.e0_r8,2,sp1,sp2,sp3,sp4)
2727 
2728  do i = 1, n_prof
2729 
2730  psi_prof(i) = float(i-1)/float(n_prof-1)
2731 
2732  fdf_dpsi(i) = spwert(n_prof_in,psi_prof(i),sp1,sp2,sp3,sp4,psi_norm,abltg)
2733 
2734  enddo
2735 
2736 elseif ((iopt_f .eq. 3) .or. (iopt_f .eq. 4)) then
2737 
2738 !DPC this is a guess! I'm also not sure why both this and the previous option overlap
2739  write(*,*) ' HELENA : using current profile as input'
2740 
2741  call spline(n_prof_in,psi_norm,current_in,0.e0_r8,0.e0_r8,2,sp1,sp2,sp3,sp4)
2742 
2743  rbnd_av = 0.e0_r8
2744  orbnd_av = 0.e0_r8
2745  do i=1,n_bnd
2746  rbnd_av = rbnd_av + r_bnd(i)
2747  orbnd_av = orbnd_av + 1.e0_r8/ r_bnd(i)
2748  enddo
2749  rbnd_av = rbnd_av / float(n_bnd)
2750  orbnd_av = orbnd_av / float(n_bnd)
2751 
2752  do i = 1, n_prof
2753 
2754  zjz_psi(i) = spwert(n_prof_in,psi_prof(i),sp1,sp2,sp3,sp4,psi_norm,abltg)
2755 
2756  si = sqrt(psi_prof(i))
2757 
2758  r_av = rgeo + si * ( rbnd_av - rgeo)
2759  or_av = 1./rgeo + si * (orbnd_av - 1./rgeo)
2760 
2761  if (iopt_f .eq. 4) fdf_dpsi(i) = ( mu_zero * ( - zjz_psi(i) - r_av * dp_dpsi(i) )/ or_av )
2762 
2763  enddo
2764 
2765 endif
2766 
2767 allocate(p_psi(n_prof),f_psi(n_prof))
2768 
2769 dpsi = 1./float(n_prof)
2770 sump = 0.
2771 sumf = 0.
2772 p_psi = 0.
2773 f_psi = 0.
2774 
2775 p_psi(n_prof) = p_bnd
2776 
2777 do i = 1, n_prof - 1
2778  sump = sump - (dp_dpsi(n_prof-i+1)+dp_dpsi(n_prof-i))*dpsi/2.
2779  p_psi(n_prof-i) = sump * abs(ps_axis) + p_bnd
2780 
2781  sumf = sumf - (fdf_dpsi(n_prof-i+1)+fdf_dpsi(n_prof-i))*dpsi/2.
2782  f_psi(n_prof-i) = sumf * abs(ps_axis)
2783 
2784 !DPC write(*,*) i, p_psi(n_prof-i),f_psi(n_prof-i)
2785 enddo
2786 
2787 call lplot6(2,2,psi_prof,dp_dpsi,n_prof,'dp/dpsi')
2788 call lplot6(2,3,psi_prof,fdf_dpsi,n_prof,'fdf/dpsi')
2789 call lplot6(3,2,psi_prof,p_psi,n_prof,'pressure')
2790 call lplot6(3,3,psi_prof,f_psi,n_prof,'F**2-F0**2')
2791 
2792 return
2793 end subroutine initialise_profiles
2794 
2795 subroutine plot_solution
2796 use helena_grid
2797 use helena_elements
2798 use itm_types
2799 implicit none
2800 integer :: i, ngr, ngs, kf, kv, vertex, nodes(4), nc
2801 real (r8) :: psi_max, psi_min, rmin, rmax, zmin, zmax, zc(3)
2802 real (r8) :: xx(4,4), yy(4,4), ps(4,4)
2803 character*19 :: label
2804 
2805 label= 'SOLUTION'
2806 
2807 psi_max = maxval(psi(1,:))
2808 psi_min = minval(psi(1,:))
2809 
2810 CALL nframe(22,11,1,r_min,r_max,z_min,z_max,label,19,'R [m]',5,'Z [m]',5)
2811 
2812 nc = 3
2813 zc(1) = -max(abs(psi_max),abs(psi_min))
2814 zc(2) = 0.
2815 zc(3) = abs(zc(1))
2816 
2817 do i=1,n_elms
2818 
2819  nodes(1) = elm_list(1,i)
2820  nodes(2) = elm_list(2,i)
2821  nodes(3) = elm_list(3,i)
2822  nodes(4) = elm_list(4,i)
2823 
2824  xx = 0.
2825  yy = 0.
2826  ps = 0.
2827 
2828  do ngr = 1, 4 ! 4 Gaussian points
2829  do ngs = 1, 4 ! 4 Gaussian points
2830 
2831  do kf = 1, 4 ! 4 basis functions
2832  do kv = 1, 4 ! 4 vertices
2833 
2834  vertex = nodes(kv)
2835 
2836  xx(ngr,ngs) = xx(ngr,ngs) + rr(kf,vertex) * h(ngr,ngs,kv,kf)
2837  yy(ngr,ngs) = yy(ngr,ngs) + zz(kf,vertex) * h(ngr,ngs,kv,kf)
2838  ps(ngr,ngs) = ps(ngr,ngs) + psi(kf,vertex) * h(ngr,ngs,kv,kf)
2839 
2840  enddo
2841  enddo
2842  enddo
2843  enddo
2844 
2845  call cplotm(2,1,-2,xx,yy,4,-4,1,1,ps,4,zc,nc,'Solution',8,'R [m]',5,'Z [m]',5)
2846 
2847 enddo
2848 call lincol(0)
2849 return
2850 end subroutine plot_solution
2851 
2852 
2853 subroutine plot_elements
2854 use helena_grid
2855 use helena_elements
2856 use itm_types
2857 implicit none
2858 integer :: i, n1, n2, n3, n4
2859 real (r8) :: rmin, rmax, zmin, zmax
2860 character*19 :: label
2861 
2862 label= 'FINITE ELEMENT GRID'
2863 
2864 rmin = minval(rr(1,1:nr*np)); rmax = maxval(rr(1,1:nr*np))
2865 zmin = minval(zz(1,1:nr*np)); zmax = maxval(zz(1,1:nr*np))
2866 
2867 CALL nframe(22,11,1,rmin,rmax,zmin,zmax,label,19,'R [m]',5,'Z [m]',5)
2868 
2869 do i=1, n_elms
2870 
2871  n1 = elm_list(1,i)
2872  n2 = elm_list(2,i)
2873  n3 = elm_list(3,i)
2874  n4 = elm_list(4,i)
2875 
2876  call plotcu(rr(1,n1), rr(3,n1), zz(1,n1), zz(3,n1), rr(1,n2), rr(3,n2), zz(1,n2), zz(3,n2))
2877  call plotcu(rr(1,n2), rr(2,n2), zz(1,n2), zz(2,n2), rr(1,n3), rr(2,n3), zz(1,n3), zz(2,n3))
2878  call plotcu(rr(1,n4), rr(3,n4), zz(1,n4), zz(3,n4), rr(1,n3), rr(3,n3), zz(1,n3), zz(3,n3))
2879  call plotcu(rr(1,n1), rr(2,n1), zz(1,n1), zz(2,n1), rr(1,n4), rr(2,n4), zz(1,n4), zz(2,n4))
2880 
2881 enddo
2882 
2883 return
2884 end subroutine plot_elements
2885 
2886 
2887 subroutine solve_matrix(amix,solve_only,error_iteration)
2888 use helena_matrix
2889 use helena_grid
2890 use helena_elements
2891 use itm_types
2892 implicit none
2893 logical :: solve_only
2894 integer :: i, j, istart, info
2895 real (r8) :: error_iteration, amix
2896 
2897 !write(*,*) n_matrix,n_diag,lda
2898 
2899 if (.not. solve_only ) then
2900  call dpbtrf('L',n_matrix,n_diag,aa,lda,info) ! factorisation (lapack)
2901  if (info .ne. 0) write(*,*) ' dpbtrf : ',info
2902 endif
2903 
2904 call dpbtrs('L',n_matrix,n_diag,1,aa,lda,bb,n_matrix,info) ! solve (lapack)
2905 if (info .ne. 0) write(*,*) ' dpbtrs : ',info
2906 
2907 error_iteration = 0
2908 
2909 do i=1,n_nodes
2910  do j=1,4
2911  error_iteration = error_iteration + abs(psi(j,index_inverse(i)) - bb(4*(i-1)+j))
2912  psi(j,index_inverse(i)) = amix * psi(j,index_inverse(i)) + (1. - amix) * bb(4*(i-1)+j)
2913  enddo
2914 enddo
2915 
2916 error_iteration = error_iteration / float(4*n_nodes)
2917 
2918 return
2919 end subroutine solve_matrix
2920 
2921 
2922 subroutine matrix_gs(ps_axis,rhs_only)
2923 use helena_grid
2924 use helena_elements
2925 use helena_gauss_4
2926 use helena_matrix
2927 use helena_constants
2928 use itm_types
2929 implicit none
2930 
2931 logical :: rhs_only
2932 integer :: nodes(4)
2933 real (r8) :: xx(4,4), xr(4,4), xs(4,4), yr(4,4), ys(4,4), xjac(4,4), ps(4,4), psn(4,4)
2934 real (r8) :: vx(4,4,4,4), vy(4,4,4,4), rhs(4,4)
2935 real (r8) :: ps_axis, sumq, sumk
2936 integer :: ngr, ngs, kf, kv, lf ,lv, i, vertex, nrow, nrow2, ncol, ncol2
2937 !real (r8) fdfdpsi,dpdpsi
2938 integer n_dof,noff,jstart,j
2939 
2940 lda = 4*(np+1) + 9
2941 n_dof = 4*nr*np
2942 n_matrix = n_dof
2943 n_diag = 4*(np+1) + 7
2944 
2945 if (.not. allocated(aa)) allocate(aa(lda,n_dof))
2946 if (.not. allocated(bb)) allocate(bb(n_dof))
2947 
2948 if (.not. rhs_only) aa = 0.
2949 bb = 0.
2950 
2951 do i=1, n_elms
2952 
2953  nodes(1) = elm_list(1,i)
2954  nodes(2) = elm_list(2,i)
2955  nodes(3) = elm_list(3,i)
2956  nodes(4) = elm_list(4,i)
2957 
2958  xr = 0.
2959  xs = 0.
2960  yr = 0.
2961  ys = 0.
2962  xx = 0.
2963  ps = 0.
2964 
2965  do ngr = 1, 4 ! 4 Gaussian points
2966  do ngs = 1, 4 ! 4 Gaussian points
2967  do kf = 1, 4 ! 4 basis functions
2968  do kv = 1, 4 ! 4 vertices
2969 
2970  vertex = nodes(kv)
2971 
2972  xx(ngr,ngs) = xx(ngr,ngs) + rr(kf,vertex) * h(ngr,ngs,kv,kf)
2973  ps(ngr,ngs) = ps(ngr,ngs) + psi(kf,vertex) * h(ngr,ngs,kv,kf)
2974 
2975  xr(ngr,ngs) = xr(ngr,ngs) + rr(kf,vertex) * hr(ngr,ngs,kv,kf)
2976  xs(ngr,ngs) = xs(ngr,ngs) + rr(kf,vertex) * hs(ngr,ngs,kv,kf)
2977  yr(ngr,ngs) = yr(ngr,ngs) + zz(kf,vertex) * hr(ngr,ngs,kv,kf)
2978  ys(ngr,ngs) = ys(ngr,ngs) + zz(kf,vertex) * hs(ngr,ngs,kv,kf)
2979 
2980  enddo
2981  enddo
2982 
2983  xjac(ngr,ngs) = xr(ngr,ngs)*ys(ngr,ngs) - xs(ngr,ngs)*yr(ngr,ngs)
2984 
2985  enddo
2986  enddo
2987 
2988  psn(:,:) = (ps_axis - ps(:,:)) / ps_axis
2989 
2990  do ngr = 1, 4
2991  do ngs = 1, 4
2992 
2993  rhs(ngr,ngs) = - ( fdfdpsi(psn(ngr,ngs)) + mu_zero * xx(ngr,ngs)*xx(ngr,ngs)*dpdpsi(psn(ngr,ngs)) ) &
2994  * wgauss(ngr)*wgauss(ngs) * xjac(ngr,ngs) / xx(ngr,ngs)
2995 
2996  enddo
2997  enddo
2998 
2999  do kf = 1, 4
3000  do kv = 1, 4
3001  do ngr = 1, 4
3002  do ngs = 1, 4
3003 
3004  vx(ngr,ngs,kf,kv) = ys(ngr,ngs) * hr(ngr,ngs,kv,kf) - yr(ngr,ngs) * hs(ngr,ngs,kv,kf)
3005  vy(ngr,ngs,kf,kv) = -xs(ngr,ngs) * hr(ngr,ngs,kv,kf) + xr(ngr,ngs) * hs(ngr,ngs,kv,kf)
3006 
3007  enddo
3008  enddo
3009  enddo
3010  enddo
3011 
3012  do kv = 1, 4
3013 
3014  nrow = 4*(index_list(nodes(kv)) - 1)
3015 
3016  do kf = 1, 4
3017 
3018  nrow2 = nrow + kf
3019 
3020  sumq = 0.
3021 
3022  do ngr = 1, 4
3023  do ngs = 1, 4
3024 
3025  sumq = sumq - rhs(ngr,ngs) * h(ngr,ngs,kv,kf)
3026 
3027  enddo
3028  enddo
3029 
3030  bb(nrow2) = bb(nrow2) + sumq
3031 
3032  if (.not. rhs_only) then
3033 
3034  do lv = 1, 4
3035 
3036  ncol = 4*(index_list(nodes(lv)) - 1)
3037 
3038  do lf = 1, 4
3039 
3040  ncol2 = ncol + lf
3041 
3042  noff = nrow2 - ncol2
3043 
3044  if (noff .ge. 0) then
3045 
3046  sumk = 0.
3047 
3048  do ngr = 1, 4
3049  do ngs = 1, 4
3050 
3051  sumk = sumk + wgauss(ngr)*wgauss(ngs) / (xjac(ngr,ngs) * xx(ngr,ngs)) &
3052  * (vx(ngr,ngs,lf,lv) * vx(ngr,ngs,kf,kv) + vy(ngr,ngs,lf,lv) * vy(ngr,ngs,kf,kv))
3053 
3054  enddo
3055  enddo
3056 
3057  aa(noff+1,ncol2) = aa(noff+1,ncol2) + sumk
3058 
3059  endif
3060 
3061  enddo
3062  enddo
3063  endif
3064  enddo
3065  enddo
3066 
3067 enddo
3068 
3069 !------------------------------- boundary conditions
3070 if (.not. rhs_only) then
3071  jstart = 4.*(nr-1)*np
3072  do j=1,np
3073  aa(1,jstart+4*j-1) = 1.e20
3074  aa(1,jstart+4*j-3) = 1.e20
3075  enddo
3076 endif
3077 return
3078 end subroutine matrix_gs
3079 
3080 
3082 use helena_grid
3083 use helena_elements
3084 use helena_gauss_4
3085 use itm_types
3086 implicit none
3087 integer :: i,j, ij1, ijn, jn, k, l, ngr, ngs, kv, kf, i0, j0
3088 real (r8) :: r, s, r0, s0
3089 
3090 n_elms = (nr-1)*np
3091 n_nodes = nr*np
3092 allocate(elm_list(4,n_elms), index_list(n_nodes), index_inverse(n_nodes))
3093 
3094 k=0
3095 do i=1,nr-1
3096  do j=1,np-1
3097  k = k + 1
3098  elm_list(1,k) = (i-1)*np + j
3099  elm_list(2,k) = (i-1)*np + j + 1
3100  elm_list(3,k) = (i )*np + j + 1
3101  elm_list(4,k) = (i )*np + j
3102  enddo
3103  k = k + 1
3104  elm_list(1,k) = (i )*np
3105  elm_list(2,k) = (i )*np - np + 1
3106  elm_list(3,k) = (i )*np + 1
3107  elm_list(4,k) = (i )*np + np
3108 enddo
3109 
3110 write(*,*) ' number of elements : ',k
3111 
3112 do i = 1, nr
3113 
3114  ij1 = (i-1)*np + 1 ! the first poloidal point
3115  index_list(ij1) = ij1
3116  index_inverse(ij1) = ij1
3117 
3118  do j = 1, np/2 ! the upper part of the poloidal plane
3119  ij1 = (i-1)*np + j + 1
3120  ijn = (i-1)*np + 2*j
3121  index_list(ij1) = ijn
3122  index_inverse(ijn) = ij1
3123  enddo
3124 
3125  do j = 1, np/2 - 1
3126  ij1 = i*np - j + 1
3127  ijn = (i-1)*np + 2*j + 1
3128  index_list(ij1) = ijn
3129  index_inverse(ijn) = ij1
3130  enddo
3131 
3132 enddo
3133 
3134 rs(1,1) = -1.; rs(1,2) = -1.; rs(2,1) = -1.; rs(2,2) = +1.
3135 rs(3,1) = +1.; rs(3,2) = +1.; rs(4,1) = +1.; rs(4,2) = -1.
3136 ij(1,1) = 0; ij(1,2) = 0; ij(2,1) = 1; ij(2,2) = 0
3137 ij(3,1) = 0; ij(3,2) = 1; ij(4,1) = 1; ij(4,2) = 1
3138 
3139 do ngr = 1, 4 ! 4 Gaussian points
3140  do ngs = 1, 4 ! 4 Gaussian points
3141 
3142  r = xgauss(ngr)
3143  s = xgauss(ngs)
3144 
3145  do kv=1,4 ! 4 corners
3146 
3147  r0 = rs(kv,1)
3148  s0 = rs(kv,2)
3149 
3150  do kf=1,4 ! 4 basis functions
3151 
3152  i0 = ij(kf,1)
3153  j0 = ij(kf,2)
3154  call cubich(i0,j0,r0,s0,r,s,h(ngr,ngs,kv,kf), hr(ngr,ngs,kv,kf), hs(ngr,ngs,kv,kf),&
3155  hrs(ngr,ngs,kv,kf),hrr(ngr,ngs,kv,kf),hss(ngr,ngs,kv,kf))
3156 
3157  enddo
3158 
3159  enddo
3160  enddo
3161 enddo
3162 
3163 return
3164 end subroutine initialise_elements
3165 
3166 
3167 
3169 !--------------------------------------------------------------------
3170 !
3171 !--------------------------------------------------------------------
3172 use helena_grid
3173 use helena_boundary
3174 use itm_types
3175 implicit none
3176 integer :: i, j, m, node
3177 real (r8) :: theta(np), s(nr)
3178 real (r8) :: pi, dt, dr, rm, drm, drmt, drmtr, radius, thtj
3179 
3180 allocate(rr(4,nr*np),zz(4,nr*np),psi(4,nr*np))
3181 
3182 pi = 2.*asin(1.)
3183 dt = 2.*pi/real(np)
3184 dr = 1./real(nr-1)
3185 
3186 do j=1,np
3187  theta(j) = dt * real(j-1)
3188 enddo
3189 
3190 do i=1,nr
3191  s(i) = float(i-1)/float(nr-1)
3192 enddo
3193 
3194 do i=1,nr
3195  do j=1,np
3196  node = np*(i-1) + j
3197  thtj = theta(j)
3198  radius = s(i)
3199 
3200  rr(1,node) = rgeo + radius * fr(1) * cos(thtj) / 2.
3201  rr(2,node) = fr(1) * cos(thtj) / 2.
3202  rr(3,node) = - radius * fr(1) * sin(thtj) / 2.
3203  rr(4,node) = - fr(1) * sin(thtj) / 2.
3204  zz(1,node) = zgeo + radius * fr(1) * sin(thtj) / 2.
3205  zz(2,node) = fr(1) * sin(thtj) / 2.
3206  zz(3,node) = radius * fr(1) * cos(thtj) / 2.
3207  zz(4,node) = fr(1) * cos(thtj) / 2.
3208 
3209 !---------------------------- KEEP ELLIPTICITY ON AXIS -----------
3210  do m = 2, mf/2
3211  if (m .eq. 2) then
3212  rm = radius * ( fr(2*m-1) * cos((m-1)*thtj) + fr(2*m) * sin((m-1)*thtj) )
3213  drm = ( fr(2*m-1) * cos((m-1)*thtj) + fr(2*m) * sin((m-1)*thtj))
3214  drmt = radius * (-fr(2*m-1) * (m-1)*sin((m-1)*thtj) + fr(2*m) * (m-1)*cos((m-1)*thtj))
3215  drmtr= (-fr(2*m-1) * (m-1)*sin((m-1)*thtj) + fr(2*m) * (m-1)*cos((m-1)*thtj))
3216  else
3217  rm = radius**(m-1) * ( fr(2*m-1) * cos((m-1)*thtj) + fr(2*m) * sin((m-1)*thtj) )
3218  drm =(m-1)*radius**(m-2) * ( fr(2*m-1) * cos((m-1)*thtj) + fr(2*m) * sin((m-1)*thtj))
3219  drmt = radius**(m-1) * (-fr(2*m-1) * (m-1)*sin((m-1)*thtj) + fr(2*m) *(m-1)*cos((m-1)*thtj))
3220  drmtr=(m-1)*radius**(m-2) * (-fr(2*m-1) * (m-1)*sin((m-1)*thtj) + fr(2*m) *(m-1)*cos((m-1)*thtj))
3221  endif
3222  rr(1,node) = rr(1,node) + rm * cos(thtj)
3223  zz(1,node) = zz(1,node) + rm * sin(thtj)
3224  rr(2,node) = rr(2,node) + drm * cos(thtj)
3225  zz(2,node) = zz(2,node) + drm * sin(thtj)
3226  rr(3,node) = rr(3,node) - rm * sin(thtj) + drmt * cos(thtj)
3227  zz(3,node) = zz(3,node) + rm * cos(thtj) + drmt * sin(thtj)
3228  rr(4,node) = rr(4,node) - drm * sin(thtj) + drmtr * cos(thtj)
3229  zz(4,node) = zz(4,node) + drm * cos(thtj) + drmtr * sin(thtj)
3230  enddo
3231  rr(2,node) = rr(2,node) * dr/2.
3232  rr(3,node) = rr(3,node) * dt/2.
3233  rr(4,node) = rr(4,node) * dr/2. * dt/2.
3234  zz(2,node) = zz(2,node) * dr/2.
3235  zz(3,node) = zz(3,node) * dt/2.
3236  zz(4,node) = zz(4,node) * dr/2. * dt/2.
3237 
3238  psi(1,node) = radius **2 - 1.
3239  psi(2,node) = 2.* radius * dr / 2.
3240  psi(3,node) = 0.
3241  psi(4,node) = 0.
3242 
3243  enddo
3244 enddo
3245 
3246 r_min = minval(rr(1,:))
3247 r_max = maxval(rr(1,:))
3248 z_min = minval(zz(1,:))
3249 z_max = maxval(zz(1,:))
3250 
3251 return
3252 end subroutine initialise_grid
3253 
3254 subroutine plot_grid(R,Z,nr,np)
3255 !-------------------------------------------------------------------
3256 ! THE X,Y GRID IS PLOTTED USING THE ISOPARAMETRIC REPRESENTATION
3257 !-------------------------------------------------------------------
3258 use itm_types
3259 implicit none
3260 real (r8) :: r(4,*),z(4,*), rmin, rmax, zmin, zmax
3261 character*19 :: label
3262 integer :: nr, np, nbase, i, j
3263 
3264 label= 'FINITE ELEMENT GRID'
3265 
3266 rmin = minval(r(1,1:nr*np)); rmax = maxval(r(1,1:nr*np))
3267 zmin = minval(z(1,1:nr*np)); zmax = maxval(z(1,1:nr*np))
3268 
3269 CALL nframe(22,1,1,rmin,rmax,zmin,zmax,label,19,'R [m]',5,'Z [m]',5)
3270 
3271 do i=1, nr
3272  do j=1, np-1
3273  nbase = j + (i-1)*np
3274  call plotcu(r(1,nbase), r(3,nbase), z(1,nbase), z(3,nbase), &
3275  r(1,nbase+1),r(3,nbase+1),z(1,nbase+1),z(3,nbase+1))
3276  enddo
3277 enddo
3278 do i=1, nr-1
3279  do j=1, np-1
3280  nbase = j + (i-1)*np
3281  call plotcu(r(1,nbase), r(2,nbase), z(1,nbase), z(2,nbase), &
3282  r(1,nbase+np),r(2,nbase+np), z(1,nbase+np),z(2,nbase+np))
3283  enddo
3284 enddo
3285 
3286 return
3287 end subroutine plot_grid
3288 
3289 
3290 subroutine plotcu(X1,X1S,Y1,Y1S,X2,X2S,Y2,Y2S)
3291 !-----------------------------------------------------------------------
3292 ! PLOTS A CUBIC LINE FROM X1,Y1 TO X2,Y2 GIVEN BY THE ARRAYS XI(1..4)
3293 ! AND YI(1..4) in an existing frame of PPPLIB
3294 !-----------------------------------------------------------------------
3295 use itm_types
3296 implicit none
3297 integer :: nplot, i
3298 parameter(nplot=21)
3299 real (r8) :: x1,x1s,y1,y1s,x2,x2s,y2,y2s
3300 real (r8) :: xp(nplot),yp(nplot), s, dummy
3301 
3302 do i=1,nplot
3303  s = -1. + 2.*float(i-1)/float(nplot-1)
3304  call cub1d(x1,x1s,x2,x2s,s,xp(i),dummy)
3305  call cub1d(y1,y1s,y2,y2s,s,yp(i),dummy)
3306 enddo
3307 call lplot6(2,1,xp,yp,-nplot,' ')
3308 
3309 return
3310 end subroutine plotcu
3311 
3312 SUBROUTINE cubich(I,J,R0,S0,R,S,H,HR,HS,HRS,HRR,HSS)
3313 !------------------------------------------------------------------
3314 ! SUBROUTINE TO CALCULATE THE VALUE OF THE CUBIC POLYNOMIALS AND
3315 ! THE DERIVATIVES OF THE CORNER MARKED BY R0,S0 AT THE POSITION R,S
3316 !------------------------------------------------------------------
3317 use itm_types
3318 implicit none
3319 integer :: i,j
3320 real (r8) :: h,hr,hs,hrs,hi,hri,hj,hsj,hrr,hss,hrri,hssj, r0, s0, r, s
3321 
3322 IF (i.EQ.0) THEN
3323  hi = - (r+r0)**2 * (r*r0-2.) / 4.
3324  hri = - (r+r0)*(r*r0-2.)/2. - r0*(r+r0)**2 / 4.
3325  hrri = - 1.5 * r * r0
3326 ELSE
3327  hi = + r0 * (r+r0)**2 * (r*r0 - 1.) / 4.
3328  hri = + r0*(r+r0)*(r*r0-1.)/2. + (r+r0)**2 /4.
3329  hrri = 1.5*r + .5*r0
3330 ENDIF
3331 IF (j.EQ.0) THEN
3332  hj = - (s+s0)**2 * (s*s0-2.) / 4.
3333  hsj = - (s+s0)*(s*s0-2.)/2. - s0*(s+s0)**2 / 4.
3334  hssj = - 1.5 * s * s0
3335 ELSE
3336  hj = + s0 * (s+s0)**2 * (s*s0 - 1.) / 4.
3337  hsj = + s0*(s+s0)*(s*s0-1.)/2. + (s+s0)**2 / 4.
3338  hssj = 1.5*s + .5*s0
3339 ENDIF
3340 h = hi * hj
3341 hr = hri * hj
3342 hs = hi * hsj
3343 hrs = hri * hsj
3344 hrr = hrri * hj
3345 hss = hi * hssj
3346 RETURN
3347 END SUBROUTINE cubich
3348 
3349 subroutine cub1d(X1,X1S,X2,X2S,S,X,XS)
3350 !-----------------------------------------------------------------------
3351 ! CUBIC HERMITE INTERPOLATION IN ONE DIMENSION
3352 !-----------------------------------------------------------------------
3353 use itm_types
3354 implicit none
3355 real (r8) :: x1,x1s,x2,x2s,s,x,xs
3356 real (r8) :: h0m,h0p,h1m,h1p,h0ms,h0ps,h1ms,h1ps
3357 
3358 h0m = (s-1.e0_r8)**2 *(s+2.e0_r8) * 0.25e0_r8
3359 h0ms = (s-1.e0_r8)*(s+2.e0_r8)/2.e0_r8 + (s-1.e0_r8)**2 * 0.25e0_r8
3360 h0p = -(s+1.e0_r8)**2 *(s-2.e0_r8) * 0.25e0_r8
3361 h0ps = -(s+1.e0_r8)*(s-2.e0_r8)/2.e0_r8 - (s+1.e0_r8)**2 * 0.25e0_r8
3362 h1m = (s-1.e0_r8)**2 *(s+1.e0_r8) * 0.25e0_r8
3363 h1ms = (s-1.e0_r8)*(s+1.e0_r8)/2. + (s-1.e0_r8)**2 * 0.25e0_r8
3364 h1p = (s+1.e0_r8)**2 *(s-1.e0_r8) * 0.25e0_r8
3365 h1ps = (s+1.e0_r8)*(s-1.e0_r8)/2.e0_r8 + (s+1.e0_r8)**2 * 0.25e0_r8
3366 
3367 x = x1*h0m + x1s*h1m + x2*h0p + x2s*h1p
3368 xs = x1*h0ms + x1s*h1ms + x2*h0ps + x2s*h1ps
3369 
3370 return
3371 end subroutine cub1d
3372 
3373 subroutine fshape
3374 !-----------------------------------------------------------------------
3375 !
3376 !-----------------------------------------------------------------------
3377 use helena_boundary
3378 use helena_constants
3379 use itm_types
3380 implicit none
3381 real (r8) :: xj, yj, ga
3382 real (r8), allocatable :: theta(:), gamma(:), xv(:),yv(:)
3383 real (r8) :: angle, error, gamm
3384 real (r8), allocatable :: tht_tmp(:), fr_tmp(:), work(:)
3385 real (r8), allocatable :: tht_sort(:), fr_sort(:), dfr_sort(:)
3386 integer, allocatable :: index_order(:)
3387 real (r8) :: tht, rbnd_av, orbnd_av, values(4)
3388 integer :: m, igrinv, i, j, ishape, ieast(1), iwest(1), n_bnd_short
3389 parameter(error = 1.d-8)
3390 
3391 allocate(fr(mf+2))
3392 allocate(theta(mf),gamma(mf),xv(mf),yv(mf))
3393 
3394 if (n_bnd .gt. 1) then
3395 
3396  write(*,*) ' fshape : (R,Z) set given on ',n_bnd,' points'
3397 
3398  reast = maxval(r_bnd)
3399  rwest = minval(r_bnd)
3400  ieast = maxloc(r_bnd)
3401  iwest = minloc(r_bnd)
3402  rgeo = (reast + rwest) /2.
3403  zgeo = (z_bnd(ieast(1))+z_bnd(iwest(1)))/2.
3404  amin = (reast - rwest)/2.
3405 
3406  write(*,'(A,3f12.8)') ' Rgeo, Zgeo : ',rgeo,zgeo,amin
3407 
3408  allocate(tht_tmp(n_bnd),fr_tmp(n_bnd),work(3*n_bnd+6))
3409  allocate(tht_sort(n_bnd+2),fr_sort(n_bnd+2),dfr_sort(n_bnd+2))
3410  allocate(index_order(n_bnd+2))
3411 
3412  rbnd_av = 0.
3413  orbnd_av = 0.
3414 
3415  do i=1,n_bnd
3416 
3417  tht_tmp(i) = atan2(z_bnd(i)-zgeo,r_bnd(i)-rgeo)
3418 
3419 ! if (i .gt. 1) then
3420 ! if (tht_tmp(i) .lt. tht_tmp(i-1)) tht_tmp(i) = tht_tmp(i) + 2.*PI
3421 ! endif
3422 
3423  fr_tmp(i) = sqrt((r_bnd(i)-rgeo)**2 + (z_bnd(i)-zgeo)**2)
3424 
3425 ! write(*,'(i5,2f12.8)') i,tht_tmp(i),fr_tmp(i)
3426 
3427  rbnd_av = rbnd_av + r_bnd(i)
3428  orbnd_av = orbnd_av + 1. / r_bnd(i)
3429 
3430  enddo
3431 
3432  if (abs(tht_tmp(n_bnd) - tht_tmp(1)) .lt. 1.e-6) n_bnd = n_bnd - 1
3433 
3434  rbnd_av = rbnd_av / float(n_bnd)
3435  orbnd_av = orbnd_av / float(n_bnd)
3436 
3437 ! write(*,*) ' Rbnd_av : ',Rbnd_av
3438 ! write(*,*) ' ORbnd_av : ',ORbnd_av
3439 
3440  call qsort2(index_order,n_bnd,tht_tmp)
3441 
3442  do i=1,n_bnd
3443  tht_sort(i) = tht_tmp(index_order(i))
3444  fr_sort(i) = fr_tmp(index_order(i))
3445 ! write(*,*) i,tht_sort(i),fr_sort(i)
3446  enddo
3447 
3448  n_bnd_short = n_bnd
3449  do i=2,n_bnd
3450 
3451  if ((tht_sort(i) - tht_sort(1)) .gt. 2.*pi) then
3452  n_bnd_short = i - 1
3453  exit
3454  endif
3455 
3456  enddo
3457 
3458  if (abs(tht_sort(n_bnd_short)- tht_sort(1)) .lt. 1.e-6) then
3459  tht_sort(n_bnd_short) = tht_sort(1) + 2.*pi
3460  fr_sort(n_bnd_short) = fr_sort(1)
3461  else
3462  tht_sort(n_bnd_short+1) = tht_sort(1) + 2.*pi
3463  fr_sort(n_bnd_short+1) = fr_sort(1)
3464  n_bnd_short = n_bnd_short + 1
3465  endif
3466 
3467 ! write(*,*) ' n_bnd, n_bnd_short : ',n_bnd, n_bnd_short
3468 
3469  call tb15a(n_bnd_short,tht_sort,fr_sort,dfr_sort,work,6)
3470 
3471  do i = 1, mf
3472 
3473  tht = 2.*pi * float(i-1)/float(mf)
3474 
3475  if (tht .lt. tht_sort(1)) tht = tht + 2.*pi
3476  if (tht .gt. tht_sort(n_bnd_short)) tht = tht - 2.*pi
3477 
3478  call tg02a(0,n_bnd_short,tht_sort,fr_sort,dfr_sort,tht,values)
3479 
3480  fr(i) = values(1)
3481  enddo
3482 
3483 else
3484 
3485  write(*,*) ' fshape : using moments'
3486 
3487 !------------------------------------ THETA(GAMMA(J)) ------------
3488  do j=1,mf
3489 
3490  ga = 2*pi*(j-1.)/REAL(mf)
3491 
3492  if (ga .le. pi) then
3493  xj= amin * cos(ga + tria_u*sin(ga) + quad_u*sin(2*ga))
3494  yj= ellip * amin * sin(ga)
3495  else
3496  xj= amin * cos(ga + tria_l*sin(ga) + quad_l*sin(2*ga))
3497  yj= ellip * amin * sin(ga)
3498  endif
3499  theta(j) = atan2(yj,xj)
3500 
3501  enddo
3502 
3503 !-------- INVERSION OF THETA(GAMMA(J)) TO GAMMA(THETA(J)) ------ --
3504  CALL grid2nv(theta,gamma,mf,error,igrinv)
3505 
3506  do j=1,mf
3507  gamm=gamma(j)
3508 
3509  if (ga .le. pi) then
3510  xv(j) = amin * cos(gamm + tria_u*sin(gamm) + quad_u*sin(2*gamm))
3511  yv(j) = ellip * amin * sin(gamm)
3512  else
3513  xv(j) = amin * cos(gamm + tria_l*sin(gamm) + quad_l*sin(2*gamm))
3514  yv(j) = ellip * amin * sin(gamm)
3515  endif
3516 
3517  enddo
3518 
3519  DO j=1,mf
3520  fr(j) = sqrt(xv(j)**2 + yv(j)**2)
3521  enddo
3522 
3523  deallocate(theta, gamma, xv, yv)
3524 
3525 endif
3526 
3527 !-------------- FOURIER COEFFICIENTS FRFNUL AND FRF(M) OF FR(J).
3528 call rft2(fr,mf,1)
3529 
3530 do m=1,mf
3531  fr(m) = 2. * fr(m) / float(mf)
3532 enddo
3533 do m=2,mf,2
3534  fr(m) = - fr(m)
3535 enddo
3536 RETURN
3537 END subroutine fshape
3538 
3539 subroutine findaxis
3540 !-----------------------------------------------------------------------
3541 !-----------------------------------------------------------------------
3542 use helena_grid
3543 use helena_elements
3544 use helena_boundary
3545 use helena_gauss_4
3546 use helena_axis
3547 use itm_types
3548 implicit none
3549 real (r8) :: ps_tmp(4,4), psi_min, axis_min
3550 integer :: nodes(4), i, ngr, ngs, kf, kv, vertex, elm_min, ij_axis(2), ifail
3551 real (r8) :: x(2), r, s, xerr, ferr, rs_tolerance, zpsir, zpsis
3552 real (r8) :: drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss
3553 real (r8) :: dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss
3554 real (r8) :: dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss
3555 real (r8) :: ejac, dr_dz, dr_dr, ds_dz, ds_dr, dps_drr, dps_dzz
3556 integer :: node1, node2, node3, node4
3557 !real (r8) :: fdia
3558 logical :: early_exit
3559 parameter(rs_tolerance = 1.d-8)
3560 
3561 early_exit = .false.
3562 !---------------------------------- first see if axis is in the same element as before
3563 if ((ielm_ax .ge. 1) .and. (ielm_ax .le. n_elms)) then
3564  nodes(1) = elm_list(1,ielm_ax)
3565  nodes(2) = elm_list(2,ielm_ax)
3566  nodes(3) = elm_list(3,ielm_ax)
3567  nodes(4) = elm_list(4,ielm_ax)
3568 
3569  call mnewtax(psi(1:4,nodes(1)),psi(1:4,nodes(2)),psi(1:4,nodes(3)),psi(1:4,nodes(4)),r,s,xerr,ferr,ifail)
3570 
3571  if ((ifail .eq. 0) .and. ((abs(r)-1.) .le. rs_tolerance) .and. ((abs(s)-1.) .le. rs_tolerance)) then
3572 
3573  call interp2(psi(1:4,nodes(1)),psi(1:4,nodes(2)),psi(1:4,nodes(3)),psi(1:4,nodes(4)),r,s,ps_axis,zpsir,zpsis)
3574  call interp1(rr(1:4,nodes(1)),rr(1:4,nodes(2)),rr(1:4,nodes(3)),rr(1:4,nodes(4)),r,s,r_axis)
3575  call interp1(zz(1:4,nodes(1)),zz(1:4,nodes(2)),zz(1:4,nodes(3)),zz(1:4,nodes(4)),r,s,z_axis)
3576 
3577  r_ax = r
3578  s_ax = s
3579 
3580  write(*,*) ' EARLY EXIT !'
3581  write(*,'(A,3f12.8)') ' magnetic axis : ',r_axis,z_axis,ps_axis
3582  write(*,'(A,f12.8)') ' delta (EARLY EXIT) : ',(r_axis-rgeo)/amin
3583  early_exit = .true.
3584 
3585  endif
3586 endif
3587 
3588 if (.not. early_exit) then
3589 
3590  psi_min = 1.d20
3591 
3592  do i=1,n_elms/2
3593 
3594  nodes(1) = elm_list(1,i)
3595  nodes(2) = elm_list(2,i)
3596  nodes(3) = elm_list(3,i)
3597  nodes(4) = elm_list(4,i)
3598 
3599  ps_tmp = 0.
3600 
3601  do ngr = 1, 4
3602  do ngs= 1, 4
3603 
3604  do kf = 1, 4 ! 4 basis functions
3605  do kv = 1, 4 ! 4 vertices
3606 
3607  vertex = nodes(kv)
3608 
3609  ps_tmp(ngr,ngs) = ps_tmp(ngr,ngs) + psi(kf,vertex) * h(ngr,ngs,kv,kf)
3610 
3611  enddo
3612  enddo
3613  enddo
3614  enddo
3615 
3616  axis_min = minval(ps_tmp)
3617 
3618  if (psi_min .gt. axis_min) then
3619  psi_min = axis_min
3620  elm_min = i
3621  ij_axis = minloc(ps_tmp)
3622  endif
3623 
3624  enddo
3625 
3626  nodes(1) = elm_list(1,elm_min)
3627  nodes(2) = elm_list(2,elm_min)
3628  nodes(3) = elm_list(3,elm_min)
3629  nodes(4) = elm_list(4,elm_min)
3630 
3631  r=xgauss(ij_axis(1)) ; s=xgauss(ij_axis(2))
3632 
3633 ! write(*,'(A,e14.6,i6,2e14.6)') 'minimum psi estimate : ',psi_min,elm_min,r,s
3634 
3635  call mnewtax(psi(1:4,nodes(1)),psi(1:4,nodes(2)),psi(1:4,nodes(3)),psi(1:4,nodes(4)),r,s,xerr,ferr,ifail)
3636 
3637  if (ifail .ne. 0 ) write(*,*) ' MNEWTAX : ifail = ',ifail
3638 
3639  r_ax = r
3640  s_ax = s
3641  ielm_ax = elm_min
3642 
3643 ! write(*,*) ' find_axis : ',r_ax,s_ax,ielm_ax
3644 
3645 endif
3646 
3647 node1 = elm_list(1,ielm_ax)
3648 node2 = elm_list(2,ielm_ax)
3649 node3 = elm_list(3,ielm_ax)
3650 node4 = elm_list(4,ielm_ax)
3651 
3652 call interp(rr(:,nodes(1)),rr(:,nodes(2)),rr(:,nodes(3)),rr(:,nodes(4)),r_ax,s_ax, &
3653  r_axis,drrg1_dr,drrg1_ds,drrg1_drs,drrg1_drr,drrg1_dss)
3654 call interp(zz(:,nodes(1)),zz(:,nodes(2)),zz(:,nodes(3)),zz(:,nodes(4)),r_ax,s_ax, &
3655  z_axis,dzzg1_dr,dzzg1_ds,dzzg1_drs,dzzg1_drr,dzzg1_dss)
3656 call interp(psi(:,nodes(1)),psi(:,nodes(2)),psi(:,nodes(3)),psi(:,nodes(4)),r_ax,s_ax, &
3657  ps_axis,dpsg1_dr,dpsg1_ds,dpsg1_drs,dpsg1_drr,dpsg1_dss)
3658 
3659 ejac = drrg1_dr * dzzg1_ds - drrg1_ds * dzzg1_dr
3660 
3661 if (ejac .ne. 0.e0_r8) then
3662  dr_dz = - drrg1_ds / ejac
3663  dr_dr = + dzzg1_ds / ejac
3664  ds_dz = + drrg1_dr / ejac
3665  ds_dr = - dzzg1_dr / ejac
3666 
3667  dps_drr = dpsg1_drr * dr_dr * dr_dr + 2.e0_r8*dpsg1_drs * dr_dr * ds_dr + dpsg1_dss * ds_dr * ds_dr
3668  dps_dzz = dpsg1_drr * dr_dz * dr_dz + 2.e0_r8*dpsg1_drs * dr_dz * ds_dz + dpsg1_dss * ds_dz * ds_dz
3669 
3670  crr_axis = dps_drr / 2.
3671  czz_axis = dps_dzz / 2.
3672 
3673  b_axis = fdia(0.e0_r8) / r_axis
3674  q_axis = b_axis /(2.e0_r8*sqrt(crr_axis*czz_axis))
3675 endif
3676 
3677 write(*,'(A,4f14.8)') ' magnetic axis : ',r_axis,z_axis,ps_axis,q_axis
3678 
3679 RETURN
3680 END subroutine findaxis
3681 
3682 SUBROUTINE mnewtax(ps1, ps2, ps3, ps4, r, s, errx, errf, ifail)
3683 !-------------------------------------------------------------------------
3684 ! ROUTINE TO SOLVE TWO NONLINEAR EQUATIONS USING NEWTONS METHOD FROM
3685 ! NUMERICAL RECIPES.
3686 ! LU DECOMPOSITION REPLACED BY EXPLICIT SOLUTION OF 2X2 MATRIX.
3687 !-------------------------------------------------------------------------
3688 use itm_types
3689 implicit none
3690 REAL (R8) :: ps1(4), ps2(4), ps3(4), ps4(4)
3691 REAL (R8) :: r, s, x(2), fvec(2),fjac(2,2)
3692 REAL (R8) :: tolf,tolx, errf, errx
3693 INTEGER :: ntrial, i, k, ifail
3694 REAL (R8) :: p(2)
3695 real (r8) zpsi,zpsir,zpsis,zpsirs,zpsirr,zpsiss,temp,dis
3696 
3697 ntrial = 50
3698 tolx = 1.d-8
3699 tolf = 1.d-16
3700 
3701 x(1) = r
3702 x(2) = s
3703 
3704 ifail = 999
3705 
3706 do k=1,ntrial
3707 
3708  call interp(ps1,ps2,ps3,ps4,x(1),x(2),zpsi,zpsir,zpsis,zpsirs,zpsirr,zpsiss)
3709 
3710 ! write(*,'(i3,5e16.8)') k,x(1),x(2),zpsi,zpsir,zpsis
3711 
3712  fvec(1) = zpsir
3713  fvec(2) = zpsis
3714  fjac(1,1) = zpsirr
3715  fjac(1,2) = zpsirs
3716  fjac(2,1) = zpsirs
3717  fjac(2,2) = zpsiss
3718 
3719  errf=abs(fvec(1))+abs(fvec(2))
3720 
3721  if (errf .le. tolf) then
3722  r = x(1)
3723  s = x(2)
3724 ! write(*,'(A,2e16.8,i5)') ' newton (1) : ',errf,errx,k
3725  ifail = 0
3726  return
3727  endif
3728 
3729  p = -fvec
3730 
3731  temp = p(1)
3732  dis = fjac(2,2)*fjac(1,1)-fjac(1,2)*fjac(2,1)
3733  if (dis .ne. 0.e0_r8) then
3734  p(1) = (fjac(2,2)*p(1)-fjac(1,2)*p(2))/dis
3735  p(2) = (fjac(1,1)*p(2)-fjac(2,1)*temp)/dis
3736  endif
3737 
3738  errx=abs(p(1)) + abs(p(2))
3739 
3740  p = min(p,+0.5e0_r8)
3741  p = max(p,-0.5e0_r8)
3742 
3743  x = x + p
3744 
3745  x = max(x,-1.e0_r8)
3746  x = min(x,+1.e0_r8)
3747 
3748  if (errx .le. tolx) then
3749  r = x(1)
3750  s = x(2)
3751 ! write(*,'(A,2e16.8,i5)') ' newton (2) : ',errf,errx,k
3752  ifail = 0
3753  return
3754  endif
3755 
3756 enddo
3757 
3758 return
3759 end SUBROUTINE mnewtax
3760 
3761 SUBROUTINE interp(XN1,XN2,XN3,XN4,R,S,X,XR,XS,XRS,XRR,XSS)
3762 !----------------------------------------------------------------------
3763 ! SUBROUTINE CALCULATES THE INTERPOLATED VALUE OF THE FUNCTION X GIVEN
3764 ! BY XI(1..4) AT THE FOUR NODES USING BI-CUBIC HERMITE ELEMENTS
3765 !----------------------------------------------------------------------
3766 use itm_types
3767 implicit none
3768 REAL (R8) :: xn1(4),xn2(4),xn3(4),xn4(4)
3769 REAL (R8) :: r,s,x,xr,xs,xrs,xrr,xss
3770 REAL (R8) :: hi0m,hri0m,hrri0m,hi1m,hri1m,hrri1m,hj0m,hsj0m,hssj0m,hj1m,hsj1m,hssj1m
3771 REAL (R8) :: hi0p,hri0p,hrri0p,hi1p,hri1p,hrri1p,hj0p,hsj0p,hssj0p,hj1p,hsj1p,hssj1p
3772 
3773 hi0m = - (r-1.e0_r8)**2 * (-r-2.e0_r8) * 0.25e0_r8
3774 hri0m = - (r-1.e0_r8)*(-r-2.e0_r8)*0.5e0_r8 +(r-1.e0_r8)**2 * 0.25e0_r8
3775 hrri0m = + 1.5e0_r8 * r
3776 hi1m = - (r-1.e0_r8)**2 * (-r-1.e0_r8) * 0.25e0_r8
3777 hri1m = - (r-1.e0_r8)*(-r-1.e0_r8)*0.5e0_r8 + (r-1.e0_r8)**2 *0.25e0_r8
3778 hrri1m = + 1.5e0_r8 * r - .5e0_r8
3779 
3780 hj0m = - (s-1.e0_r8)**2 * (-s-2.e0_r8) * 0.25e0_r8
3781 hsj0m = - (s-1.e0_r8)*(-s-2.e0_r8)*0.5 +(s-1.e0_r8)**2 * 0.25e0_r8
3782 hssj0m = + 1.5e0_r8 * s
3783 hj1m = - (s-1.e0_r8)**2 * (-s-1.e0_r8) * 0.25e0_r8
3784 hsj1m = - (s-1.e0_r8)*(-s-1.e0_r8)*0.5e0_r8 + (s-1.e0_r8)**2 * 0.25e0_r8
3785 hssj1m = + 1.5e0_r8 * s - .5e0_r8
3786 
3787 hi0p = - (r+1.e0_r8)**2 * (r-2.e0_r8) * 0.25e0_r8
3788 hri0p = - (r+1.e0_r8)*(r-2.e0_r8)*0.5e0_r8 - (r+1.e0_r8)**2 * 0.25e0_r8
3789 hrri0p = - 1.5e0_r8 * r
3790 hi1p = + (r+1.e0_r8)**2 * (r-1.e0_r8) * 0.25e0_r8
3791 hri1p = + (r+1.e0_r8)*(r-1.e0_r8)*0.5e0_r8 + (r+1.e0_r8)**2 * 0.25e0_r8
3792 hrri1p = + 1.5e0_r8 * r + .5e0_r8
3793 
3794 hj0p = - (s+1.e0_r8)**2 * (s-2.e0_r8) * 0.25e0_r8
3795 hsj0p = - (s+1.e0_r8)*(s-2.e0_r8)*0.5e0_r8 - (s+1.e0_r8)**2 * 0.25e0_r8
3796 hssj0p = - 1.5e0_r8 * s
3797 hj1p = + (s+1.e0_r8)**2 * (s-1.e0_r8) * 0.25e0_r8
3798 hsj1p = + (s+1.e0_r8)*(s-1.e0_r8)*0.5e0_r8 + (s+1.e0_r8)**2 * 0.25e0_r8
3799 hssj1p = + 1.5e0_r8 * s + .5e0_r8
3800 
3801 x = hi0m*hj0m * xn1(1) + hi1m*hj0m * xn1(2) + hi0m*hj1m * xn1(3) + hi1m*hj1m * xn1(4) &
3802  + hi0m*hj0p * xn2(1) + hi1m*hj0p * xn2(2) + hi0m*hj1p * xn2(3) + hi1m*hj1p * xn2(4) &
3803  + hi0p*hj0m * xn4(1) + hi1p*hj0m * xn4(2) + hi0p*hj1m * xn4(3) + hi1p*hj1m * xn4(4) &
3804  + hi0p*hj0p * xn3(1) + hi1p*hj0p * xn3(2) + hi0p*hj1p * xn3(3) + hi1p*hj1p * xn3(4)
3805 
3806 xr = hri0m*hj0m * xn1(1) + hri1m*hj0m * xn1(2) + hri0m*hj1m * xn1(3) + hri1m*hj1m * xn1(4) &
3807  + hri0m*hj0p * xn2(1) + hri1m*hj0p * xn2(2) + hri0m*hj1p * xn2(3) + hri1m*hj1p * xn2(4) &
3808  + hri0p*hj0m * xn4(1) + hri1p*hj0m * xn4(2) + hri0p*hj1m * xn4(3) + hri1p*hj1m * xn4(4) &
3809  + hri0p*hj0p * xn3(1) + hri1p*hj0p * xn3(2) + hri0p*hj1p * xn3(3) + hri1p*hj1p * xn3(4)
3810 
3811 xs = hi0m*hsj0m * xn1(1) + hi1m*hsj0m * xn1(2) + hi0m*hsj1m * xn1(3) + hi1m*hsj1m * xn1(4) &
3812  + hi0m*hsj0p * xn2(1) + hi1m*hsj0p * xn2(2) + hi0m*hsj1p * xn2(3) + hi1m*hsj1p * xn2(4) &
3813  + hi0p*hsj0m * xn4(1) + hi1p*hsj0m * xn4(2) + hi0p*hsj1m * xn4(3) + hi1p*hsj1m * xn4(4) &
3814  + hi0p*hsj0p * xn3(1) + hi1p*hsj0p * xn3(2) + hi0p*hsj1p * xn3(3) + hi1p*hsj1p * xn3(4)
3815 
3816 xrr = hrri0m*hj0m * xn1(1) + hrri1m*hj0m * xn1(2) + hrri0m*hj1m * xn1(3) + hrri1m*hj1m * xn1(4) &
3817  + hrri0m*hj0p * xn2(1) + hrri1m*hj0p * xn2(2) + hrri0m*hj1p * xn2(3) + hrri1m*hj1p * xn2(4) &
3818  + hrri0p*hj0m * xn4(1) + hrri1p*hj0m * xn4(2) + hrri0p*hj1m * xn4(3) + hrri1p*hj1m * xn4(4) &
3819  + hrri0p*hj0p * xn3(1) + hrri1p*hj0p * xn3(2) + hrri0p*hj1p * xn3(3) + hrri1p*hj1p * xn3(4)
3820 
3821 xss = hi0m*hssj0m * xn1(1) + hi1m*hssj0m * xn1(2) + hi0m*hssj1m * xn1(3) + hi1m*hssj1m * xn1(4) &
3822  + hi0m*hssj0p * xn2(1) + hi1m*hssj0p * xn2(2) + hi0m*hssj1p * xn2(3) + hi1m*hssj1p * xn2(4) &
3823  + hi0p*hssj0m * xn4(1) + hi1p*hssj0m * xn4(2) + hi0p*hssj1m * xn4(3) + hi1p*hssj1m * xn4(4) &
3824  + hi0p*hssj0p * xn3(1) + hi1p*hssj0p * xn3(2) + hi0p*hssj1p * xn3(3) + hi1p*hssj1p * xn3(4)
3825 
3826 xrs = hri0m*hsj0m * xn1(1) + hri1m*hsj0m * xn1(2) + hri0m*hsj1m * xn1(3) + hri1m*hsj1m * xn1(4) &
3827  + hri0m*hsj0p * xn2(1) + hri1m*hsj0p * xn2(2) + hri0m*hsj1p * xn2(3) + hri1m*hsj1p * xn2(4) &
3828  + hri0p*hsj0m * xn4(1) + hri1p*hsj0m * xn4(2) + hri0p*hsj1m * xn4(3) + hri1p*hsj1m * xn4(4) &
3829  + hri0p*hsj0p * xn3(1) + hri1p*hsj0p * xn3(2) + hri0p*hsj1p * xn3(3) + hri1p*hsj1p * xn3(4)
3830 
3831 RETURN
3832 END SUBROUTINE interp
3833 
3834 
3835 SUBROUTINE interp1(XN1,XN2,XN3,XN4,R,S,X)
3836 !----------------------------------------------------------------------
3837 ! SUBROUTINE CALCULATES THE INTERPOLATED VALUE OF THE FUNCTION X GIVEN
3838 ! BY XI(1..4) AT THE FOUR NODES USING BI-CUBIC HERMITE ELEMENTS
3839 !----------------------------------------------------------------------
3840 use itm_types
3841 implicit none
3842 REAL (R8) xn1(4),xn2(4),xn3(4),xn4(4)
3843 real (r8) r,s,x,hi0m,hi1m,hj0m,hj1m,hi0p,hi1p,hj0p,hj1p
3844 
3845 hi0m = - (r-1.)**2 * (-r-2.) * 0.25
3846 hi1m = - (r-1.)**2 * (-r-1.) * 0.25
3847 
3848 hj0m = - (s-1.)**2 * (-s-2.) * 0.25
3849 hj1m = - (s-1.)**2 * (-s-1.) * 0.25
3850 
3851 hi0p = - (r+1.)**2 * (r-2.) * 0.25
3852 hi1p = + (r+1.)**2 * (r-1.) * 0.25
3853 
3854 hj0p = - (s+1.)**2 * (s-2.) * 0.25
3855 hj1p = + (s+1.)**2 * (s-1.) * 0.25
3856 
3857 x = hi0m*hj0m * xn1(1) + hi1m*hj0m * xn1(2) + hi0m*hj1m * xn1(3) + hi1m*hj1m * xn1(4) &
3858  + hi0m*hj0p * xn2(1) + hi1m*hj0p * xn2(2) + hi0m*hj1p * xn2(3) + hi1m*hj1p * xn2(4) &
3859  + hi0p*hj0m * xn4(1) + hi1p*hj0m * xn4(2) + hi0p*hj1m * xn4(3) + hi1p*hj1m * xn4(4) &
3860  + hi0p*hj0p * xn3(1) + hi1p*hj0p * xn3(2) + hi0p*hj1p * xn3(3) + hi1p*hj1p * xn3(4)
3861 
3862 RETURN
3863 END SUBROUTINE interp1
3864 
3865 SUBROUTINE interp2(XN1,XN2,XN3,XN4,R,S,X,XR,XS)
3866 !----------------------------------------------------------------------
3867 ! SUBROUTINE CALCULATES THE INTERPOLATED VALUE OF THE FUNCTION X GIVEN
3868 ! BY XI(1..4) AT THE FOUR NODES USING BI-CUBIC HERMITE ELEMENTS
3869 !----------------------------------------------------------------------
3870 use itm_types
3871 implicit none
3872 REAL (R8) xn1(4),xn2(4),xn3(4),xn4(4)
3873 real (r8) r,s,x,xr,xs,hi0m,hri0m,hi1m,hri1m,hj0m,hsj0m,hj1m,hsj1m,hi0p,hri0p, &
3874  hi1p,hri1p,hj0p,hsj0p,hj1p,hsj1p
3875 
3876 hi0m = - (r-1.)**2 * (-r-2.) * 0.25
3877 hri0m = - (r-1.)*(-r-2.)*0.5 +(r-1.)**2 * 0.25
3878 hi1m = - (r-1.)**2 * (-r-1.) * 0.25
3879 hri1m = - (r-1.)*(-r-1.)*0.5 + (r-1.)**2 * 0.25
3880 hj0m = - (s-1.)**2 * (-s-2.) * 0.25
3881 hsj0m = - (s-1.)*(-s-2.)*0.5 +(s-1.)**2 * 0.25
3882 hj1m = - (s-1.)**2 * (-s-1.) * 0.25
3883 hsj1m = - (s-1.)*(-s-1.)*0.5 + (s-1.)**2 * 0.25
3884 
3885 hi0p = - (r+1.)**2 * (r-2.) * 0.25
3886 hri0p = - (r+1.)*(r-2.)*0.5 - (r+1.)**2 * 0.25
3887 hi1p = + (r+1.)**2 * (r-1.) * 0.25
3888 hri1p = + (r+1.)*(r-1.)*0.5 + (r+1.)**2 * 0.25
3889 
3890 hj0p = - (s+1.)**2 * (s-2.) * 0.25
3891 hsj0p = - (s+1.)*(s-2.)*0.5 - (s+1.)**2 * 0.25
3892 hj1p = + (s+1.)**2 * (s-1.) * 0.25
3893 hsj1p = + (s+1.)*(s-1.)*0.5 + (s+1.)**2 * 0.25
3894 
3895 x = hi0m*hj0m * xn1(1) + hi1m*hj0m * xn1(2) + hi0m*hj1m * xn1(3) + hi1m*hj1m * xn1(4) &
3896  + hi0m*hj0p * xn2(1) + hi1m*hj0p * xn2(2) + hi0m*hj1p * xn2(3) + hi1m*hj1p * xn2(4) &
3897  + hi0p*hj0m * xn4(1) + hi1p*hj0m * xn4(2) + hi0p*hj1m * xn4(3) + hi1p*hj1m * xn4(4) &
3898  + hi0p*hj0p * xn3(1) + hi1p*hj0p * xn3(2) + hi0p*hj1p * xn3(3) + hi1p*hj1p * xn3(4)
3899 
3900 xr = hri0m*hj0m * xn1(1) + hri1m*hj0m * xn1(2) + hri0m*hj1m * xn1(3) + hri1m*hj1m * xn1(4) &
3901  + hri0m*hj0p * xn2(1) + hri1m*hj0p * xn2(2) + hri0m*hj1p * xn2(3) + hri1m*hj1p * xn2(4) &
3902  + hri0p*hj0m * xn4(1) + hri1p*hj0m * xn4(2) + hri0p*hj1m * xn4(3) + hri1p*hj1m * xn4(4) &
3903  + hri0p*hj0p * xn3(1) + hri1p*hj0p * xn3(2) + hri0p*hj1p * xn3(3) + hri1p*hj1p * xn3(4)
3904 
3905 xs = hi0m*hsj0m * xn1(1) + hi1m*hsj0m * xn1(2) + hi0m*hsj1m * xn1(3) + hi1m*hsj1m * xn1(4) &
3906  + hi0m*hsj0p * xn2(1) + hi1m*hsj0p * xn2(2) + hi0m*hsj1p * xn2(3) + hi1m*hsj1p * xn2(4) &
3907  + hi0p*hsj0m * xn4(1) + hi1p*hsj0m * xn4(2) + hi0p*hsj1m * xn4(3) + hi1p*hsj1m * xn4(4) &
3908  + hi0p*hsj0p * xn3(1) + hi1p*hsj0p * xn3(2) + hi0p*hsj1p * xn3(3) + hi1p*hsj1p * xn3(4)
3909 
3910 RETURN
3911 END SUBROUTINE interp2
3912 
3913 SUBROUTINE interp3(XN1,XN2,XN3,XN4,YN1,YN2,YN3,YN4,PN1,PN2,PN3,PN4,R,S, &
3914  x,xr,xs,yr,ys,ps)
3915 !----------------------------------------------------------------------
3916 ! SUBROUTINE CALCULATES THE INTERPOLATED VALUE OF THE FUNCTION X GIVEN
3917 ! BY XI(1..4) AT THE FOUR NODES USING BI-CUBIC HERMITE ELEMENTS
3918 !----------------------------------------------------------------------
3919 use itm_types
3920 implicit none
3921 REAL (R8) xn1(4),xn2(4),xn3(4),xn4(4)
3922 REAL (R8) yn1(4),yn2(4),yn3(4),yn4(4)
3923 REAL (R8) pn1(4),pn2(4),pn3(4),pn4(4)
3924 real (r8) r,s,x,xr,xs,yr,ys,ps,hi0m,hri0m,hi1m,hri1m,hj0m,hsj0m, &
3925  hj1m,hsj1m,hi0p,hri0p,hi1p,hri1p,hj0p,hsj0p,hj1p,hsj1p
3926 
3927 hi0m = - (r-1.)**2 * (-r-2.) * 0.25
3928 hri0m = - (r-1.)*(-r-2.)*0.5 +(r-1.)**2 * 0.25
3929 hi1m = - (r-1.)**2 * (-r-1.) * 0.25
3930 hri1m = - (r-1.)*(-r-1.)*0.5 + (r-1.)**2 * 0.25
3931 hj0m = - (s-1.)**2 * (-s-2.) * 0.25
3932 hsj0m = - (s-1.)*(-s-2.)*0.5 +(s-1.)**2 * 0.25
3933 hj1m = - (s-1.)**2 * (-s-1.) * 0.25
3934 hsj1m = - (s-1.)*(-s-1.)*0.5 + (s-1.)**2 * 0.25
3935 
3936 hi0p = - (r+1.)**2 * (r-2.) * 0.25
3937 hri0p = - (r+1.)*(r-2.)*0.5 - (r+1.)**2 * 0.25
3938 hi1p = + (r+1.)**2 * (r-1.) * 0.25
3939 hri1p = + (r+1.)*(r-1.)*0.5 + (r+1.)**2 * 0.25
3940 
3941 hj0p = - (s+1.)**2 * (s-2.) * 0.25
3942 hsj0p = - (s+1.)*(s-2.)*0.5 - (s+1.)**2 * 0.25
3943 hj1p = + (s+1.)**2 * (s-1.) * 0.25
3944 hsj1p = + (s+1.)*(s-1.)*0.5 + (s+1.)**2 * 0.25
3945 
3946 x = hi0m*hj0m * xn1(1) + hi1m*hj0m * xn1(2) + hi0m*hj1m * xn1(3) + hi1m*hj1m * xn1(4) &
3947  + hi0m*hj0p * xn2(1) + hi1m*hj0p * xn2(2) + hi0m*hj1p * xn2(3) + hi1m*hj1p * xn2(4) &
3948  + hi0p*hj0m * xn4(1) + hi1p*hj0m * xn4(2) + hi0p*hj1m * xn4(3) + hi1p*hj1m * xn4(4) &
3949  + hi0p*hj0p * xn3(1) + hi1p*hj0p * xn3(2) + hi0p*hj1p * xn3(3) + hi1p*hj1p * xn3(4)
3950 
3951 xr = hri0m*hj0m * xn1(1) + hri1m*hj0m * xn1(2) + hri0m*hj1m * xn1(3) + hri1m*hj1m * xn1(4) &
3952  + hri0m*hj0p * xn2(1) + hri1m*hj0p * xn2(2) + hri0m*hj1p * xn2(3) + hri1m*hj1p * xn2(4) &
3953  + hri0p*hj0m * xn4(1) + hri1p*hj0m * xn4(2) + hri0p*hj1m * xn4(3) + hri1p*hj1m * xn4(4) &
3954  + hri0p*hj0p * xn3(1) + hri1p*hj0p * xn3(2) + hri0p*hj1p * xn3(3) + hri1p*hj1p * xn3(4)
3955 
3956 xs = hi0m*hsj0m * xn1(1) + hi1m*hsj0m * xn1(2) + hi0m*hsj1m * xn1(3) + hi1m*hsj1m * xn1(4) &
3957  + hi0m*hsj0p * xn2(1) + hi1m*hsj0p * xn2(2) + hi0m*hsj1p * xn2(3) + hi1m*hsj1p * xn2(4) &
3958  + hi0p*hsj0m * xn4(1) + hi1p*hsj0m * xn4(2) + hi0p*hsj1m * xn4(3) + hi1p*hsj1m * xn4(4) &
3959  + hi0p*hsj0p * xn3(1) + hi1p*hsj0p * xn3(2) + hi0p*hsj1p * xn3(3) + hi1p*hsj1p * xn3(4)
3960 
3961 ps = hi0m*hj0m * pn1(1) + hi1m*hj0m * pn1(2) + hi0m*hj1m * pn1(3) + hi1m*hj1m * pn1(4) &
3962  + hi0m*hj0p * pn2(1) + hi1m*hj0p * pn2(2) + hi0m*hj1p * pn2(3) + hi1m*hj1p * pn2(4) &
3963  + hi0p*hj0m * pn4(1) + hi1p*hj0m * pn4(2) + hi0p*hj1m * pn4(3) + hi1p*hj1m * pn4(4) &
3964  + hi0p*hj0p * pn3(1) + hi1p*hj0p * pn3(2) + hi0p*hj1p * pn3(3) + hi1p*hj1p * pn3(4)
3965 
3966 yr = hri0m*hj0m * yn1(1) + hri1m*hj0m * yn1(2) + hri0m*hj1m * yn1(3) + hri1m*hj1m * yn1(4) &
3967  + hri0m*hj0p * yn2(1) + hri1m*hj0p * yn2(2) + hri0m*hj1p * yn2(3) + hri1m*hj1p * yn2(4) &
3968  + hri0p*hj0m * yn4(1) + hri1p*hj0m * yn4(2) + hri0p*hj1m * yn4(3) + hri1p*hj1m * yn4(4) &
3969  + hri0p*hj0p * yn3(1) + hri1p*hj0p * yn3(2) + hri0p*hj1p * yn3(3) + hri1p*hj1p * yn3(4)
3970 
3971 ys = hi0m*hsj0m * yn1(1) + hi1m*hsj0m * yn1(2) + hi0m*hsj1m * yn1(3) + hi1m*hsj1m * yn1(4) &
3972  + hi0m*hsj0p * yn2(1) + hi1m*hsj0p * yn2(2) + hi0m*hsj1p * yn2(3) + hi1m*hsj1p * yn2(4) &
3973  + hi0p*hsj0m * yn4(1) + hi1p*hsj0m * yn4(2) + hi0p*hsj1m * yn4(3) + hi1p*hsj1m * yn4(4) &
3974  + hi0p*hsj0p * yn3(1) + hi1p*hsj0p * yn3(2) + hi0p*hsj1p * yn3(3) + hi1p*hsj1p * yn3(4)
3975 
3976 RETURN
3977 END SUBROUTINE interp3
3978 
3979 
3980 SUBROUTINE rft2(DATA,NR,KR)
3981 !*****************************************************************
3982 ! REAL FOURIER TRANSFORM. *
3983 ! INPUT: NR REAL COEFFICIENTS *
3984 ! DATA(1),DATA(1+KR),....,DATA(1+(NR-1)*KR). *
3985 ! OUTPUT: NR/2+1 COMPLEX COEFFICIENTS *
3986 ! (DATA(1), DATA(1+KR)) *
3987 ! (DATA(1+2*KR), DATA(1+3*KR)) *
3988 ! ............................. *
3989 ! (DATA(1+NR*KR),DATA(1+(NR+1)*KR). *
3990 ! THE CALLING PROGRAM SHOULD HAVE DATA DIMENSIONED WITH AT LEAST *
3991 ! (NR+1)*KR+1 ELEMENTS. (I.E., NR+2 IF INCREMENT KR=1). *
3992 ! LASL ROUTINE MAY 75, CALLING FFT2 AND RTRAN2. *
3993 !*****************************************************************
3994 use itm_types
3995 implicit none
3996 real (r8) :: data(*)
3997 integer :: kr,nr, ktran
3998 
3999 CALL fft2(DATA(1),DATA(kr+1),nr/2,-(kr+kr))
4000 CALL rtran2(DATA,nr,kr,1)
4001 RETURN
4002 END SUBROUTINE rft2
4003 
4004 SUBROUTINE rtran2(DATA,NR,KR,KTRAN)
4005 !*****************************************************************
4006 ! INTERFACE BETWEEN RFT2, RFI2, AND FFT2. *
4007 ! THE CALLING PROGRAM SHOULD HAVE DATA DIMENSIONED WITH AT LEAST *
4008 ! (NR+1)*KR+1 ELEMENTS. *
4009 ! LASL ROUTINE MAY 75, CALLED FROM RFT2 AND RFI2. *
4010 !*****************************************************************
4011 use itm_types
4012 implicit none
4013 real (r8) :: data(*), theta, dc, ds, ws, wc, sumr, difr, sumi, difi
4014 real (r8) :: tr, ti, wca
4015 integer :: nr, kr, ktran, ks, n, nmax, kmax, k, nk
4016 
4017 ks=2*kr
4018 n=nr/2
4019 nmax=n*ks+2
4020 kmax=nmax/2
4021 theta=1.5707963267949/float(n)
4022 dc=2.*sin(theta)**2
4023 ds=sin(2.*theta)
4024 ws=0.
4025 
4026 IF (ktran .LE. 0) THEN
4027  wc=-1.0
4028  ds=-ds
4029 ELSE
4030  wc=1.0
4031  DATA(nmax-1)=DATA(1)
4032  DATA(nmax-1+kr)=DATA(kr+1)
4033 ENDIF
4034 DO k=1,kmax,ks
4035  nk=nmax-k
4036  sumr=.5*(DATA(k)+DATA(nk))
4037  difr=.5*(DATA(k)-DATA(nk))
4038  sumi=.5*(DATA(k+kr)+DATA(nk+kr))
4039  difi=.5*(DATA(k+kr)-DATA(nk+kr))
4040  tr=wc*sumi-ws*difr
4041  ti=ws*sumi+wc*difr
4042  DATA(k)=sumr+tr
4043  DATA(k+kr)=difi-ti
4044  DATA(nk)=sumr-tr
4045  DATA(nk+kr)=-difi-ti
4046  wca=wc-dc*wc-ds*ws
4047  ws=ws+ds*wc-dc*ws
4048  wc=wca
4049 enddo
4050 return
4051 end SUBROUTINE rtran2
4052 
4053 SUBROUTINE fft2 (DATAR,DATAI,N,INC)
4054 !*****************************************************************
4055 ! FFT2 FORTRAN VERSION CLAIR NIELSON MAY 75. *
4056 !*****************************************************************
4057 use itm_types
4058 implicit none
4059 real (r8) :: datar(*), datai(*)
4060 integer :: n, ninc
4061 real (r8) tempr,tempi,theta,sinth,wstpr,wstpi,wr,wi
4062 integer inc,ktran,ks,ip0,ip3,irev,i,ibit,ip1,ip2,i1,i3,j0,j1
4063 
4064 ktran=isign(-1,inc)
4065 ks=iabs(inc)
4066 ip0=ks
4067 ip3=ip0*n
4068 irev=1
4069 
4070  DO i=1,ip3,ip0
4071  IF(i.LT.irev) THEN
4072  tempr=datar(i)
4073  tempi=datai(i)
4074  datar(i)=datar(irev)
4075  datai(i)=datai(irev)
4076  datar(irev)=tempr
4077  datai(irev)=tempi
4078  ENDIF
4079  ibit=ip3/2
4080  10 IF(irev.GT.ibit) THEN
4081  irev=irev-ibit
4082  ibit=ibit/2
4083  IF(ibit.GE.ip0) goto 10
4084  ENDIF
4085  irev=irev+ibit
4086  enddo
4087  ip1=ip0
4088  theta=REAL(ktran)*3.1415926535898
4089  30 IF(ip1.GE.ip3) return
4090  ip2=ip1+ip1
4091  sinth=sin(.5*theta)
4092  wstpr=-2.*sinth*sinth
4093  wstpi=sin(theta)
4094  wr=1.
4095  wi=0.
4096  DO i1=1,ip1,ip0
4097  DO i3=i1,ip3,ip2
4098  j0=i3
4099  j1=j0+ip1
4100  tempr=wr*datar(j1)-wi*datai(j1)
4101  tempi=wr*datai(j1)+wi*datar(j1)
4102  datar(j1)=datar(j0)-tempr
4103  datai(j1)=datai(j0)-tempi
4104  datar(j0)=datar(j0)+tempr
4105  datai(j0)=datai(j0)+tempi
4106  enddo
4107  tempr=wr
4108  wr=wr*wstpr-wi*wstpi+wr
4109  wi=wi*wstpr+tempr*wstpi+wi
4110  enddo
4111  ip1=ip2
4112  theta=.5*theta
4113  goto 30
4114 RETURN
4115 END SUBROUTINE fft2
4116 
4117 
4118 SUBROUTINE fsum2(F,T,FFNUL,FFCOS,FFSIN,MHARM)
4119 !-----------------------------------------------------------------------
4120 ! FOURIER SYNTHESIS OF GENERAL FUNCTION F(T) AT SINGLE POINT T.
4121 !-----------------------------------------------------------------------
4122 use itm_types
4123 implicit none
4124 integer :: mharm, m
4125 real (r8) :: ffnul, ffcos(*), ffsin(*), f, t, s, c, co, ca, si, sum
4126 
4127 co=cos(t)
4128 si=sin(t)
4129 c=1.
4130 s=0.
4131 sum=.5*ffnul
4132 do m=1,mharm
4133  ca=c*co-s*si
4134  s=s*co+c*si
4135  c=ca
4136  sum=sum+ffcos(m)*c + ffsin(m)*s
4137 enddo
4138 f=sum
4139 RETURN
4140 END SUBROUTINE fsum2
4141 
4142 SUBROUTINE grid2nv(TIN,TOUT,JPTS,ACC,IGRD)
4143 !------------------------------------------------------------------------
4144 ! THE FUNCTION TIN(TOUT), GIVEN ON THE GRID TOUT=2*PI*(J-1)/JPTS,
4145 ! IS INVERTED TO GIVE TOUT(TIN) ON THE GRID TIN=2*PI*(I-1)/JPTS.
4146 ! THIS IS DONE BY DETERMINING THE ZEROS OF THE FUNCTION
4147 ! Y(T)=T+SUM(GF(M)*SIN(M*T))-2*PI*(I-1)/JPTS,
4148 ! WHERE GF(M) ARE THE FOURIER COEFFICIENTS OF G(T)=TIN(T)-T.
4149 !-----------------------------------------------------------------------
4150 use itm_types
4151 implicit none
4152 integer jmax,ninv
4153 parameter(jmax=1024,ninv=100)
4154 dimension tin(*),tout(*),t(jmax+1),g(jmax+1),gfcos(jmax/2-1),gfsin(jmax/2-1)
4155 equivalence(t(1),g(1))
4156 real (r8) tin,tout,t,g,gfcos,gfsin,acc,pi,t1,sum1,y1,t0,y0,t2,sum2,y2,gfnul
4157 integer jpts,igrd,mharm,jj,i,j1,igrdnv,ifirst,icirc,j,n
4158 
4159 pi=2. * asin(1.)
4160 mharm=jpts/2-1
4161 
4162 DO jj=2,jpts
4163  IF (tin(jj-1).GT.tin(jj)) tin(jj)=tin(jj)+2*pi
4164 ENDDO
4165 
4166 DO i=1,jpts
4167  g(i)=tin(i)-2.*pi*(i-1.)/jpts
4168 ENDDO
4169 
4170 CALL rft(g,gfnul,gfcos,gfsin,jpts,mharm)
4171 
4172 do i=1,jpts+1
4173  t(i)=2.*pi*(i-1.)/jpts
4174 enddo
4175 j1=1
4176 igrdnv=1
4177 ifirst=0
4178 icirc= - (int(tin(1)/(2*pi)+10000) - 9999)
4179 IF (abs(tin(1)).LT.1e-12) icirc=0
4180 
4181  DO 80 i=1,jpts
4182  j=j1
4183  t1=t(j) + icirc*2*pi
4184  CALL fsum2(sum1,t1,gfnul,gfcos,gfsin,mharm)
4185  y1=t1+sum1-t(i)
4186  30 CONTINUE
4187  t0=t1
4188  y0=y1
4189  IF (abs(y0).LE.acc) THEN
4190  tout(i)=t0
4191  goto 80
4192  ENDIF
4193  IF (j.NE.jpts+1) goto 31
4194  IF (ifirst.EQ.0) THEN
4195  j=1
4196  icirc=icirc+1
4197  ifirst=1
4198  ELSE
4199  goto 90
4200  ENDIF
4201  31 j=j+1
4202  t1=t(j) + icirc*2*pi
4203  CALL fsum2(sum1,t1,gfnul,gfcos,gfsin,mharm)
4204  y1=t1+sum1-t(i)
4205  IF(sign(1.0_r8,y0).EQ.sign(1.0_r8,y1)) goto 30
4206  j1=j-1
4207  DO 40 n=1,ninv
4208  t2=t0-(t1-t0)*y0/(y1-y0)
4209  CALL fsum2(sum2,t2,gfnul,gfcos,gfsin,mharm)
4210  y2=t2+sum2-t(i)
4211  IF(abs(y2).LE.acc) goto 50
4212  IF(sign(1.0_r8,y2).EQ.sign(1.0_r8,y1)) goto 45
4213  t0=t2
4214  y0=y2
4215  goto 40
4216  45 t1=t2
4217  y1=y2
4218  40 CONTINUE
4219  50 tout(i)=t2
4220  IF(n.GT.igrdnv) igrdnv=n
4221  80 CONTINUE
4222  90 RETURN
4223 
4224 END SUBROUTINE grid2nv
4225 
4226 SUBROUTINE rft(F,FFNUL,FFCOS,FFSIN,JPTS,MHARM)
4227 !-----------------------------------------------------------------------
4228 ! CALCULATES FOURIER COSINE AND SINE COEFFICIENTS FFCOS AND
4229 ! FFSIN OF THE ARRAY FF CORRESPONDING TO THE FUNCTION
4230 ! F(T)=.5*FFNUL+SUM(FFCOS(M)*COS(M*T)+FFSIN(M)*SIN(M*T))
4231 ! WHERE MHARM.LE.JPTS/2-1, FFNUL=FF(0) AND T=2*PI*(J-1)/JPTS.
4232 ! THE INPUT ARRAY F(J) IS NOT DESTROYED BY CALLING RFTCOS.
4233 ! TYPICAL USE IS FOR MHARM MUCH SMALLER THAN JPTS/2-1, SO THAT
4234 ! RFT2 CANNOT BE USED DIRECTLY.
4235 !-----------------------------------------------------------------------
4236 use itm_types
4237 implicit none
4238 integer :: jpts, jmax, mharm, j, m
4239 parameter(jmax=1024)
4240 real (r8) :: f(*),ffnul,ffcos(*),ffsin(*),fstore(jmax+2)
4241 real (r8) :: fac
4242 
4243 DO j=1,jpts
4244  fstore(j)=f(j)
4245 enddo
4246 CALL rft2(fstore,jpts,1)
4247 fac=2./jpts
4248 ffnul=fstore(1)*fac
4249 DO m=1,mharm
4250  ffcos(m)=fstore(2*m+1)*fac
4251  ffsin(m) = - fstore(2*m+2)*fac
4252 ENDDO
4253 RETURN
4254 END SUBROUTINE rft
4255 
4256 SUBROUTINE spline(N,X,Y,ALFA,BETA,TYP,A,B,C,D)
4257 !-----------------------------------------------------------------------
4258 ! INPUT:
4259 !
4260 ! N ANZAHL DER KNOTEN
4261 ! X ARRAY DER X-WERTE
4262 ! Y ARRAY DER Y-WERTE
4263 ! ALFA RANDBEDINGUNG IN X(1)
4264 ! BETA " IN X(N)
4265 ! TYP = 0 NOT-A-KNOT SPLINE
4266 ! 1 ALFA, BETA 1. ABLEITUNGEN VORGEGEBEN
4267 ! 2 " " 2. " "
4268 ! 3 " " 3. " "
4269 !
4270 ! BEMERKUNG: MIT TYP = 2 UND ALFA = BETA = 0 ERHAELT MAN
4271 ! EINEN NATUERLICHEN SPLINE
4272 !
4273 ! OUTPUT:
4274 !
4275 ! A, B, C, D ARRAYS DER SPLINEKOEFFIZIENTEN
4276 ! S = A(I) + B(I)*(X-X(I)) + C(I)*(X-X(I))**2+ D(I)*(X-X(I))**3
4277 !
4278 ! BEI ANWENDUNGSFEHLERN WIRD DAS PROGRAMM MIT ENTSPRECHENDER
4279 ! FEHLERMELDUNG ABGEBROCHEN
4280 !-----------------------------------------------------------------------
4281 use itm_types
4282 implicit none
4283  INTEGER n, typ
4284  REAL (R8) x(n), y(n), alfa, beta, a(n), b(n), c(n), d(n)
4285  INTEGER i, ierr
4286  REAL (R8) h(1001)
4287 
4288 
4289  IF((typ.LT.0).OR.(typ.GT.3)) THEN
4290  WRITE(*,*) ' ERROR IN ROUTINE SPLINE: WRONG TYPE'
4291  stop
4292  ENDIF
4293 
4294  IF (n.LT.3) THEN
4295  WRITE(*,*) ' ERROR IN ROUTINE SPLINE: N < 3 '
4296  stop
4297  ENDIF
4298 
4299 ! BERECHNE DIFFERENZ AUFEINENDERFOLGENDER X-WERTE UND
4300 ! UNTERSUCHE MONOTONIE
4301 
4302  DO i = 1, n-1
4303  h(i) = x(i+1)- x(i)
4304  IF ( h(i).LE. 0.0) THEN
4305  WRITE(*,*) ' NON-MONOTONIC COORDINATE IN SPLINE: X(I-1)>=X(I)'
4306  stop
4307  ENDIF
4308  ENDDO
4309 
4310 ! AUFSTELLEN DES GLEICHUNGSSYSTEMS
4311 
4312  DO i = 1, n-2
4313  a(i) = 3.0 * ((y(i+2)-y(i+1)) / h(i+1) - (y(i+1)-y(i)) / h(i))
4314  b(i) = h(i)
4315  c(i) = h(i+1)
4316  d(i) = 2.0 * (h(i) + h(i+1))
4317  ENDDO
4318 
4319 ! BERUECKSICHTIGEN DER RANDBEDINGUNGEN
4320 !
4321 ! NOT-A-KNOT
4322 
4323  IF (typ.EQ.0) THEN
4324  a(1) = a(1) * h(2) / (h(1) + h(2))
4325  a(n-2) = a(n-2) * h(n-2) / (h(n-1) + h(n-2))
4326  d(1) = d(1) - h(1)
4327  d(n-2) = d(n-2) - h(n-1)
4328  c(1) = c(1) - h(1)
4329  b(n-2) = b(n-2) - h(n-1)
4330  ENDIF
4331 
4332 ! 1. ABLEITUNG VORGEGEBEN
4333 
4334  IF (typ.EQ.1) THEN
4335  a(1) = a(1) - 1.5 * ((y(2)-y(1)) / h(1) - alfa)
4336  a(n-2) = a(n-2) - 1.5 * (beta - (y(n)-y(n-1)) / h(n-1))
4337  d(1) = d(1) - 0.5 * h(1)
4338  d(n-2) = d(n-2) - 0.5 * h(n-1)
4339  ENDIF
4340 
4341 ! 2. ABLEITUNG VORGEGEBEN
4342 
4343  IF (typ.EQ.2) THEN
4344  a(1) = a(1) - 0.5 * alfa * h(1)
4345  a(n-2) = a(n-2) - 0.5 * beta * h(n-1)
4346  ENDIF
4347 
4348 ! 3. ABLEITUNG VORGEGEBEN
4349 
4350  IF (typ.EQ.3 ) THEN
4351  a(1) = a(1) + 0.5 * alfa * h(1) * h(1)
4352  a(n-2) = a(n-2) - 0.5 * beta * h(n-1)* h(n-1)
4353  d(1) = d(1) + h(1)
4354  d(n-2) = d(n-2) + h(n-1)
4355  ENDIF
4356 
4357 ! BERECHNUNG DER KOEFFIZIENTEN
4358 
4359  CALL sgtsl(n-2,b,d,c,a,ierr)
4360 
4361  IF(ierr.NE.0) THEN
4362  WRITE(*,21)
4363  stop
4364  ENDIF
4365 
4366 ! UEBERSCHREIBEN DES LOESUNGSVEKTORS
4367 
4368  CALL dcopy(n-2,a,1,c(2),1)
4369 
4370 ! IN ABHAENGIGKEIT VON DEN RANDBEDINGUNGEN WIRD DER 1. UND
4371 ! DER LETZTE WERT VON C KORRIGIERT
4372 
4373  IF (typ.EQ.0) THEN
4374  c(1) = c(2) + h(1) * (c(2)-c(3)) / h(2)
4375  c(n) = c(n-1) + h(n-1) * (c(n-1)-c(n-2)) / h(n-2)
4376  ENDIF
4377 
4378  IF (typ.EQ.1) THEN
4379  c(1) = 1.5*((y(2)-y(1)) / h(1) - alfa) / h(1) - 0.5 * c(2)
4380  c(n) = -1.5*((y(n)-y(n-1)) / h(n-1)-beta) / h(n-1)-0.5*c(n-1)
4381  ENDIF
4382 
4383  IF (typ.EQ.2) THEN
4384  c(1) = 0.5 * alfa
4385  c(n) = 0.5 * beta
4386  ENDIF
4387 
4388  IF (typ.EQ.3) THEN
4389  c(1) = c(2) - 0.5 * alfa * h(1)
4390  c(n) = c(n-1) + 0.5 * beta * h(n-1)
4391  ENDIF
4392 
4393  CALL dcopy(n,y,1,a,1)
4394 
4395  DO i = 1, n-1
4396  b(i) = (a(i+1)-a(i)) / h(i) - h(i) * (c(i+1)+2.0 * c(i)) / 3.0
4397  d(i) = (c(i+1)-c(i)) / (3.0 * h(i))
4398  ENDDO
4399 
4400  b(n) = (3.0 * d(n-1) * h(n-1) + 2.0 * c(n-1)) * h(n-1) + b(n-1)
4401 
4402  RETURN
4403 
4404  21 FORMAT(1x,'ERROR IN SGTSL: MATRIX SINGULAR')
4405  END SUBROUTINE spline
4406 
4407 
4408 
4409 FUNCTION spwert(N,XWERT,A,B,C,D,X,ABLTG)
4410 !-----------------------------------------------------------------------
4411 ! INPUT:
4412 !
4413 ! N ANZAHL DER KNOTENPUNKTE
4414 ! XWERT STELLE AN DER FUNKTIONSWERTE BERECHNET WERDEN
4415 ! A, B, C, D ARRAYS DER SPLINEKOEFFIZIENTEN (AUS SPLINE)
4416 ! X ARRAY DER KNOTENPUNKTE
4417 !
4418 ! OUTPUT:
4419 !
4420 ! SPWERT FUNKTIONSWERT AN DER STELLE XWERT
4421 ! ABLTG(I) WERT DER I-TEN ABLEITUNG BEI XWERT
4422 !-----------------------------------------------------------------------
4423 use itm_types
4424 implicit none
4425 REAL (R8) spwert
4426  INTEGER n
4427  REAL (R8) xwert, a(n), b(n), c(n), d(n), x(n), abltg(3)
4428  INTEGER i, k, m
4429  real (r8) xx
4430 
4431 ! SUCHE PASSENDES INTERVALL (BINAERE SUCHE)
4432 
4433  i = 1
4434  k = n
4435 
4436  10 m = (i+k) / 2
4437 
4438  IF(m.NE.i) THEN
4439  IF(xwert.LT.x(m)) THEN
4440  k = m
4441  ELSE
4442  i = m
4443  ENDIF
4444  goto 10
4445  ENDIF
4446 
4447  xx = xwert - x(i)
4448 
4449  abltg(1) = (3.0 * d(i) * xx + 2.0 * c(i)) * xx + b(i)
4450  abltg(2) = 6.0 * d(i) * xx + 2.0 * c(i)
4451  abltg(3) = 6.0 * d(i)
4452 
4453  spwert = ((d(i)*xx + c(i))*xx + b(i))*xx + a(i)
4454 
4455  RETURN
4456  END FUNCTION spwert
4457 
4458 SUBROUTINE sgtsl(N,C,D,E,B,INFO)
4459 use itm_types
4460 implicit none
4461 INTEGER n,info
4462 REAL (R8) c(*),d(*),e(*),b(*)
4463 !
4464 ! SGTSL GIVEN A GENERAL TRIDIAGONAL MATRIX AND A RIGHT HAND
4465 ! SIDE WILL FIND THE SOLUTION.
4466 !
4467 ! ON ENTRY
4468 !
4469 ! N INTEGER
4470 ! IS THE ORDER OF THE TRIDIAGONAL MATRIX.
4471 !
4472 ! C REAL(N)
4473 ! IS THE SUBDIAGONAL OF THE TRIDIAGONAL MATRIX.
4474 ! C(2) THROUGH C(N) SHOULD CONTAIN THE SUBDIAGONAL.
4475 ! ON OUTPUT C IS DESTROYED.
4476 !
4477 ! D REAL(N)
4478 ! IS THE DIAGONAL OF THE TRIDIAGONAL MATRIX.
4479 ! ON OUTPUT D IS DESTROYED.
4480 !
4481 ! E REAL(N)
4482 ! IS THE SUPERDIAGONAL OF THE TRIDIAGONAL MATRIX.
4483 ! E(1) THROUGH E(N-1) SHOULD CONTAIN THE SUPERDIAGONAL.
4484 ! ON OUTPUT E IS DESTROYED.
4485 !
4486 ! B REAL(N)
4487 ! IS THE RIGHT HAND SIDE VECTOR.
4488 !
4489 ! ON RETURN
4490 !
4491 ! B IS THE SOLUTION VECTOR.
4492 !
4493 ! INFO INTEGER
4494 ! = 0 NORMAL VALUE.
4495 ! = K IF THE K-TH ELEMENT OF THE DIAGONAL BECOMES
4496 ! EXACTLY ZERO. THE SUBROUTINE RETURNS WHEN
4497 ! THIS IS DETECTED.
4498 !
4499 ! LINPACK. THIS VERSION DATED 08/14/78 .
4500 ! JACK DONGARRA, ARGONNE NATIONAL LABORATORY.
4501 !
4502 ! NO EXTERNALS
4503 ! FORTRAN ABS
4504 !
4505 ! INTERNAL VARIABLES
4506 !
4507  INTEGER k,kb,kp1,nm1,nm2
4508  REAL (R8) t
4509 ! BEGIN BLOCK PERMITTING ...EXITS TO 100
4510 
4511  info = 0
4512  c(1) = d(1)
4513  nm1 = n - 1
4514  IF (nm1 .LT. 1) go to 40
4515  d(1) = e(1)
4516  e(1) = 0.0e0
4517  e(n) = 0.0e0
4518 
4519  DO 30 k = 1, nm1
4520  kp1 = k + 1
4521 
4522 ! FIND THE LARGEST OF THE TWO ROWS
4523 
4524  IF (abs(c(kp1)) .LT. abs(c(k))) go to 10
4525 
4526 ! INTERCHANGE ROW
4527 
4528  t = c(kp1)
4529  c(kp1) = c(k)
4530  c(k) = t
4531  t = d(kp1)
4532  d(kp1) = d(k)
4533  d(k) = t
4534  t = e(kp1)
4535  e(kp1) = e(k)
4536  e(k) = t
4537  t = b(kp1)
4538  b(kp1) = b(k)
4539  b(k) = t
4540  10 CONTINUE
4541 
4542 ! ZERO ELEMENTS
4543 
4544  IF (c(k) .NE. 0.0e0) go to 20
4545  info = k
4546 ! ............EXIT
4547  go to 100
4548  20 CONTINUE
4549  t = -c(kp1)/c(k)
4550  c(kp1) = d(kp1) + t*d(k)
4551  d(kp1) = e(kp1) + t*e(k)
4552  e(kp1) = 0.0e0
4553  b(kp1) = b(kp1) + t*b(k)
4554  30 CONTINUE
4555  40 CONTINUE
4556  IF (c(n) .NE. 0.0e0) go to 50
4557  info = n
4558  go to 90
4559  50 CONTINUE
4560 
4561 ! BACK SOLVE
4562 
4563  nm2 = n - 2
4564  b(n) = b(n)/c(n)
4565  IF (n .EQ. 1) go to 80
4566  b(nm1) = (b(nm1) - d(nm1)*b(n))/c(nm1)
4567  IF (nm2 .LT. 1) go to 70
4568  DO 60 kb = 1, nm2
4569  k = nm2 - kb + 1
4570  b(k) = (b(k) - d(k)*b(k+1) - e(k)*b(k+2))/c(k)
4571  60 CONTINUE
4572  70 CONTINUE
4573  80 CONTINUE
4574  90 CONTINUE
4575  100 CONTINUE
4576 
4577 RETURN
4578 END SUBROUTINE sgtsl
4579 
4580 SUBROUTINE tb15a(N,X,F,D,W,LP)
4581 !------------------------------------------------------------------
4582 ! HSL routine for cubic spline with periodic boundary conditions
4583 ! first point must be the same as last : f(1)=f(n)
4584 ! N : number of points
4585 ! X : coordinate (input)
4586 ! F : the function values to be splined (input)
4587 ! D : the derivatives at the points (output)
4588 ! W : workspace (dimension 3N)
4589 ! LP : unit number for output
4590 !------------------------------------------------------------------
4591 use itm_types
4592 implicit none
4593 REAL (R8) zero,one,two,three
4594 parameter(zero=0.0e0,one=1.0e0,two=2.0e0,three=3.0e0)
4595 INTEGER lp,n
4596 REAL (R8) d(n),f(n),w(*),x(n)
4597 REAL (R8) a3n1,f1,f2,h1,h2,p
4598 INTEGER i,j,k,n2
4599 
4600 WRITE(*,*) f(1),f(n)
4601 IF (n.LT.4) THEN
4602  WRITE (lp,'(A39)') 'RETURN FROM TB15AD BECAUSE N TOO SMALL'
4603  w(1) = one
4604  RETURN
4605 END IF
4606 DO i = 2,n
4607  IF (x(i).LE.x(i-1)) THEN
4608  WRITE (lp,'(A29,I3,A13)') ' RETURN FROM TB15AD BECAUSE ',i,' OUT OF ORDER'
4609  write(*,*) x
4610  w(1) = two
4611  RETURN
4612  END IF
4613 ENDDO
4614 IF (f(1).NE.f(n)) THEN
4615  WRITE (lp,'(A40)') .NE.'RETURN FROM TB15AD BECAUSE F(1)F(N)'
4616  w(1) = three
4617  RETURN
4618 END IF
4619 DO i = 2,n
4620  h1 = one/ (x(i)-x(i-1))
4621  f1 = f(i-1)
4622  IF (i.EQ.n) THEN
4623  h2 = one/ (x(2)-x(1))
4624  f2 = f(2)
4625  ELSE
4626  h2 = one/ (x(i+1)-x(i))
4627  f2 = f(i+1)
4628  END IF
4629  w(3*i-2) = h1
4630  w(3*i-1) = two* (h1+h2)
4631  w(3*i) = h2
4632  d(i) = 3.0* (f2*h2*h2+f(i)* (h1*h1-h2*h2)-f1*h1*h1)
4633 ENDDO
4634 n2 = n - 2
4635 k = 5
4636 a3n1 = w(3*n-1)
4637 DO i = 2,n2
4638  p = w(k+2)/w(k)
4639  w(k+3) = w(k+3) - p*w(k+1)
4640  d(i+1) = d(i+1) - p*d(i)
4641  w(k+2) = -p*w(k-1)
4642  p = w(k-1)/w(k)
4643  a3n1 = -p*w(k-1) + a3n1
4644  d(n) = d(n) - p*d(i)
4645  k = k + 3
4646 ENDDO
4647 p = (w(k+2)+w(k-1))/w(k)
4648 a3n1 = a3n1 - p* (w(k+1)+w(k-1))
4649 d(n) = (d(n)-p*d(n-1))/a3n1
4650 DO i = 3,n
4651  j = n + 2 - i
4652  d(j) = (d(j)-w(3*j)*d(j+1)-w(3*j-2)*d(n))/w(3*j-1)
4653 ENDDO
4654 d(1) = d(n)
4655 w(1) = zero
4656 RETURN
4657 END SUBROUTINE tb15a
4658 
4659 
4660 
4661 SUBROUTINE tg02a(IX,N,U,S,D,X,V)
4662 !------------------------------------------------------------------
4663 ! HSL subroutine to calculate splined values
4664 ! N : number of points
4665 ! IX : negative 0 -> no initial guess for where xi is
4666 ! positive -> gues for index close to value X
4667 ! U : the coordinates of the spline points
4668 ! S : the function values of the spline points
4669 ! D : the derivatives on the spline points
4670 ! X : the coordinate where the output is wanted
4671 ! V(1-4) : value and derivatives of the spline interpolation
4672 !------------------------------------------------------------------
4673 use itm_types
4674 implicit none
4675 REAL (R8) x
4676 INTEGER ix,n
4677 REAL (R8) d(*),s(*),u(*),v(*)
4678 REAL (R8) a,b,c,c3,e0_r8,d1,eps,gama,h,hr,hrr,phi,s0,s1,t,theta
4679 INTEGER i,iflg,j,k
4680 
4681 eps = 1.e-33
4682 k = 0
4683 iflg = 0
4684 IF (x.LT.u(1)) go to 990
4685 IF (x.GT.u(n)) go to 991
4686 IF (ix.LT.0 .OR. iflg.EQ.0) go to 12
4687 IF (x.GT.u(j+1)) go to 1
4688 IF (x.GE.u(j)) go to 18
4689 go to 2
4690 
4691  1 j = j + 1
4692  11 IF (x.GT.u(j+1)) go to 1
4693  go to 7
4694  12 j = abs(x-u(1))/ (u(n)-u(1))* (n-1) + 1
4695  j = min(j,n-1)
4696  iflg = 1
4697  IF (x.GE.u(j)) go to 11
4698  2 j = j - 1
4699  IF (x.LT.u(j)) go to 2
4700  7 k = j
4701  h = u(j+1) - u(j)
4702  hr = 1./h
4703  hrr = (hr+hr)*hr
4704  s0 = s(j)
4705  s1 = s(j+1)
4706  e0_r8 = d(j)
4707  d1 = d(j+1)
4708  a = s1 - s0
4709  b = a - h*d1
4710  a = a - h*e0_r8
4711  c = a + b
4712  c3 = c*3.
4713  18 theta = (x-u(j))*hr
4714  phi = 1. - theta
4715  t = theta*phi
4716  gama = theta*b - phi*a
4717  v(1) = theta*s1 + phi*s0 + t*gama
4718  v(2) = theta*d1 + phi*e0_r8 + t*c3*hr
4719  v(3) = (c* (phi-theta)-gama)*hrr
4720  v(4) = -c3*hrr*hr
4721  RETURN
4722  990 IF (x.LE.u(1)-eps*max(abs(u(1)),abs(u(n)))) go to 99
4723  j = 1
4724  go to 7
4725  991 IF (x.GE.u(n)+eps*max(abs(u(1)),abs(u(n)))) go to 995
4726  j = n - 1
4727  go to 7
4728  995 k = n
4729  99 iflg = 0
4730  DO i = 1,4
4731  v(i) = 0.
4732  ENDDO
4733 RETURN
4734 END SUBROUTINE tg02a
4735 
4736 SUBROUTINE qsort2 (ORD,N,A)
4737 use itm_types
4738 implicit none
4739 !
4740 !==============SORTS THE ARRAY A(I),I=1,2,...,N BY PUTTING THE
4741 ! ASCENDING ORDER VECTOR IN ORD. THAT IS ASCENDING ORDERED A
4742 ! IS A(ORD(I)),I=1,2,...,N; DESCENDING ORDER A IS A(ORD(N-I+1)),
4743 ! I=1,2,...,N . THIS SORT RUNS IN TIME PROPORTIONAL TO N LOG N .
4744 !
4745 !
4746 ! ACM QUICKSORT - ALGORITHM #402 - IMPLEMENTED IN FORTRAN BY
4747 ! WILLIAM H. VERITY
4748 ! COMPUTATION CENTER
4749 ! PENNSYLVANIA STATE UNIVERSITY
4750 ! UNIVERSITY PARK, PA. 16802
4751 ! With correction to that algorithm.
4752 !
4753 !
4754  dimension ord(n),poplst(2,20)
4755  integer ord,poplst
4756 !
4757 ! To sort different input types change the following
4758 ! specification statements; FOR EXAMPLE, REAL A(N) or
4759 ! CHARACTER *(L) A(N) for REAL or CHARACTER sorting
4760 ! respectively similarly for X,XX,Z,ZZ,Y. L is the
4761 ! character length of the elements of A.
4762 !
4763  REAL (R8) a(n)
4764  REAL (R8) x,xx,z,zz,y
4765  integer n,ndeep,u1,l1,i,l,u,p,q,yp,ix,iz,ip,iq
4766 !
4767  ndeep=0
4768  u1=n
4769  l1=1
4770  DO 1 i=1,n
4771  1 ord(i)=i
4772  2 IF (u1.GT.l1) go to 3
4773  RETURN
4774 !
4775  3 l=l1
4776  u=u1
4777 !
4778 ! PART
4779 !
4780  4 p=l
4781  q=u
4782  x=a(ord(p))
4783  z=a(ord(q))
4784  IF (x.LE.z) go to 5
4785  y=x
4786  x=z
4787  z=y
4788  yp=ord(p)
4789  ord(p)=ord(q)
4790  ord(q)=yp
4791  5 IF (u-l.LE.1) go to 15
4792  xx=x
4793  ix=p
4794  zz=z
4795  iz=q
4796 !
4797 ! LEFT
4798 !
4799  6 p=p+1
4800  IF (p.GE.q) go to 7
4801  x=a(ord(p))
4802  IF (x.GE.xx) go to 8
4803  go to 6
4804  7 p=q-1
4805  go to 13
4806 !
4807 ! RIGHT
4808 !
4809  8 q=q-1
4810  IF (q.LE.p) go to 9
4811  z=a(ord(q))
4812  IF (z.LE.zz) go to 10
4813  go to 8
4814  9 q=p
4815  p=p-1
4816  z=x
4817  x=a(ord(p))
4818 !
4819 ! DIST
4820 !
4821  10 IF (x.LE.z) go to 11
4822  y=x
4823  x=z
4824  z=y
4825  ip=ord(p)
4826  ord(p)=ord(q)
4827  ord(q)=ip
4828  11 IF (x.LE.xx) go to 12
4829  xx=x
4830  ix=p
4831  12 IF (z.GE.zz) go to 6
4832  zz=z
4833  iz=q
4834  go to 6
4835 !
4836 ! OUT
4837 !
4838  13 CONTINUE
4839  IF (.NOT.(p.NE.ix.AND.x.NE.xx)) go to 14
4840  ip=ord(p)
4841  ord(p)=ord(ix)
4842  ord(ix)=ip
4843  14 CONTINUE
4844  IF (.NOT.(q.NE.iz.AND.z.NE.zz)) go to 15
4845  iq=ord(q)
4846  ord(q)=ord(iz)
4847  ord(iz)=iq
4848  15 CONTINUE
4849  IF (u-q.LE.p-l) go to 16
4850  l1=l
4851  u1=p-1
4852  l=q+1
4853  go to 17
4854  16 u1=u
4855  l1=q+1
4856  u=p-1
4857  17 CONTINUE
4858  IF (u1.LE.l1) go to 18
4859 !
4860 ! START RECURSIVE CALL
4861 !
4862  ndeep=ndeep+1
4863  poplst(1,ndeep)=u
4864  poplst(2,ndeep)=l
4865  go to 3
4866  18 IF (u.GT.l) go to 4
4867 !
4868 ! POP BACK UP IN THE RECURSION LIST
4869 !
4870  IF (ndeep.EQ.0) go to 2
4871  u=poplst(1,ndeep)
4872  l=poplst(2,ndeep)
4873  ndeep=ndeep-1
4874  go to 18
4875 !
4876 ! END QSORT
4877 END SUBROUTINE qsort2
4878 
4879 end module helena21_mod
subroutine initialise_elements
subroutine helena_circulating(nr_flux, np_flux, RRflux, ZZflux, PSflux, fraction_circ)
subroutine interp(XN1, XN2, XN3, XN4, R, S, X, XR, XS, XRS, XRR, XSS)
real(r8) function r_min(rminor, xaxis, i)
subroutine helena_flux_surface_integrals(nr_flux, np_flux, RR_flux, ZZ_flux, PS_flux, powers, n_int, n_var, results, q, vprime)
subroutine grid2nv(tin, tout, jpts, acc, igrd, ll)
Definition: grid2nv.f90:1
subroutine zero(x1, y1, x2, y2, func, err, x, y, izero, ll)
Definition: zero.f90:1
subroutine solve_matrix(amix, solve_only, error_iteration)
subroutine tg02a(ix, n, n_bnd, u, s, d, x, v)
Definition: tg02a.f90:1
subroutine fluxsurface_current(R_av, OR_av)
subroutine interp2(XN1, XN2, XN3, XN4, R, S, X, XR, XS)
subroutine matrix_gs(ps_axis, rhs_only)
subroutine interp1(XN1, XN2, XN3, XN4, R, S, X)
real(r8) function current_profile(psi_n)
subroutine qsort2(ORD, N, A)
subroutine initialise_profiles(n_prof_in, iopt_p, iopt_f, psi_in, pprime_in, ffprime_in, pressure_in, fdia_in, current_in)
real(r8) function dpdpsi(psi_n)
subroutine helena_remesh(nrnew, npnew, RRnew, ZZnew, PSInew)
subroutine solvem2(a, b, c, d, e, f, x, y)
subroutine cplotm(MX, MY, ILAB1, X, Y, NX, NY, INCX, INCY, Z, NDIM, ZC, NC, TITLE, NTITLE, XNAME, NXNAME, YNAME, NYNAME)
Definition: ppplib.f:1233
subroutine tb15a(n, n_bnd, x, f, d, w, lp)
Definition: tb15a.f90:1
subroutine flux_surface_add_point(s, i, iv, ifound, r_psi, s_psi, dpsi_dr, dpsi_ds)
subroutine spline(N, X, Y, ALFA, BETA, TYP, A, B, C, D)
Definition: solution6.f90:655
subroutine finplt
Definition: ppplib.f:5552
subroutine helena_volume_integrals(nr_flux, np_flux, RR_flux, ZZ_flux, PS_flux, powers, volume_integrals, n_var, n_int, n_psi)
REAL *8 function spwert(N, XWERT, A, B, C, D, X, ABLTG)
Definition: solution6.f90:155
subroutine rft2(data, nr, kr)
Definition: rft2.f90:1
subroutine update_fdf(equilibrium, xaxis)
Definition: update_fdf.f90:1
subroutine plot_flux_surfaces
subroutine fshape
subroutine helena_mapping(RR, ZZ, PSI, n_tht, n_chi)
subroutine rtran2(data, nr, kr, ktran)
Definition: rtran2.f90:1
subroutine findaxis
subroutine fsum2(f, t, ffnul, ffcos, ffsin, mharm)
Definition: fsum2.f90:1
real(r8) function fdfdpsi(psi_n)
subroutine sgtsl(n, c, d, e, b, info)
Definition: sgtsl.f90:3
subroutine current(GEOMETRY, PROFILES, TRANSPORT, SOURCES, EVOLUTION, CONTROL, j_boun, ifail, failstring)
CURRENT TRANSPORT EQUATION.
subroutine plotcu(X1, X1S, Y1, Y1S, X2, X2S, Y2, Y2S)
real(r8) function fdia(psi_n)
subroutine psi_minmax(n, psimin, psimax)
subroutine phys_values
subroutine lplot6(MX, MY, X, Y, NPTS, TITLE)
Definition: ppplib.f:51
real(r8) function, public root(a, b, c, d, sgn)
subroutine solvp3(C0, C1, C2, C3, X1, X2, X3, IFAIL)
subroutine nframe(MX, MY, IOP, XMIN, XMAX, YMIN, YMAX, TITLE, NTITLE, XNAME, NXNAME, YNAME, NYNAME)
Definition: ppplib.f:3214
subroutine gs_solve(n_iter, rhs_only, solve_only, error_iteration, amix, ifail)
real(r8) function p(a, x, xr, xs, yr, ys, psi, psir, F_dia)
subroutine plot_grid(R, Z, nr, np)
subroutine cub1d(X1, X1S, X2, X2S, S, X, XS)
subroutine plot_solution
subroutine flux_surface_add_line(i, j, r_psi, s_psi, dpsi_dr, dpsi_ds)
subroutine helena_moments(RRflux, ZZflux, nr_flux, np_flux, moments, n_moments)
subroutine begplt(NAME)
Definition: ppplib.f:5304
subroutine rft(f, ffnul, ffcos, ffsin, jpts, mharm)
Definition: rft.f90:1
subroutine lplot(MX, MY, IOP, X, Y, NPTS, INC, TITLE, NTITLE, XNAME, NXNAME, YNAME, NYNAME)
Definition: ppplib.f:240
subroutine export_helena
subroutine initialise_grid
real(r8) function dp_dpsi(flux)
Definition: dp_dpsi.f90:1
subroutine interp3(XN1, XN2, XN3, XN4, YN1, YN2, YN3, YN4, PN1, PN2, PN3, PN4, R, S, X, XR, XS, YR, YS, PS)
real(r8) function r_max(rminor, xaxis, i)
subroutine fft2(datar, datai, n, inc)
Definition: fft2.f90:1
subroutine fluxsurface_integrals(powers, n_int, n_var, results)
subroutine mnewtax(ntrial, naxis, x, n, tolx, tolf, errx, errf)
Definition: mnewtax.f90:1
real(r8) function pressure(flux)
subroutine tht_minmax(n, thtmin, thtmax)
subroutine lincol(ICOL)
Definition: ppplib.f:5977
subroutine plot_elements
subroutine pplot(MX, MY, X, Y, NPTS, INC)
Definition: ppplib.f:599
subroutine find_flux_surfaces
subroutine cubich(I, J, R0, S0, R, S, H, HR, HS, HRS, HRR, HSS)
subroutine helena21(R_bnd_in, Z_bnd_in, n_bnd_in, Rgeo_in, Zgeo_in, amin_in, ellip_in, tria_u_in, tria_l_in, quad_u_in, quad_l_in, Bgeo_in, psi_in, pprime_in, ffprime_in, pressure_in, fdia_in, current_in, n_prof_in, iopt_p, iopt_f, nr_grid, np_grid, psi_out, pprime_out, ffprime_out, pressure_out, fdia_out, current_out, qprof_out, vprime, fraction_circ, moments, n_moments, surface_powers, surface_integrals, n_var_surfaces, n_int_surfaces, volume_powers, volume_integrals, n_var_volumes, n_int_volumes, n_psi_out, n_tht_out, amin_out, Rgeo_out, Zgeo_out, area_out, volume_out, betap_out, xip_out, xli_out, beta_out, R_axis_out, Z_axis_out, B_axis_out, psi_axis_out, psi_bnd_out, RRflux, ZZflux, PSflux)