61 USE spline3d_fit_coefs
69 INTEGER:: i, j, k, iargc, numargs, isize, it,
70 & steps, num_orbs, icount, nsurfs, mn, scndry_steps
71 REAL(rprec):: s_test, theta_test, phi_test, delta,
72 & ang_in, ang_out, rdum, tstart, tend, s1, s2
73 REAL(rprec):: angle, phi_puncture, theta_puncture
74 REAL(rprec),
PARAMETER :: relerr=1.d-8, abserr=1.d-8,
76 REAL(rprec),
ALLOCATABLE,
DIMENSION(:,:):: start_points
77 REAL(rprec),
ALLOCATABLE,
DIMENSION(:):: theta_nb_tot,
78 & phi_nb_tot, s_nb_tot, r_s_nb_tot, z_s_nb_tot
80 INTEGER:: i_truncate, ilen, iargs
81 INTEGER :: local_num_orbs, norbs_tot, istat
82 CHARACTER(LEN=8):: type_in
83 CHARACTER(LEN=100):: outfile
84 CHARACTER(LEN=60):: arg1, arg2, arg3, arg4, arg5,
85 & arg6, arg7, arg8, arg9, arg10
86 CHARACTER(LEN=13),
PARAMETER:: banner =
'Version 1.20',
87 & update =
'May 10, 2013'
88 EXTERNAL rt_hand_side_dphi, rt_hand_side_dtheta, jacobian
96 CALL mpi_init(ierr_mpi)
97 IF (ierr_mpi .NE. 0)
THEN
98 WRITE(*,
'("MPI_INIT returned IER =")') ierr_mpi
101 CALL mpi_comm_size(mpi_comm_world, numprocs, ierr_mpi)
102 IF (ierr_mpi .NE. 0)
THEN
103 WRITE(*,
'("MPI_COMM_SIZE returned IER =")') ierr_mpi
106 CALL mpi_comm_rank(mpi_comm_world, myid, ierr_mpi)
107 IF (ierr_mpi .NE. 0)
THEN
108 WRITE(*,
'("MPI_COMM_RANK returned IER =")') ierr_mpi
118 WRITE(*,*)
'=================================================='
119 & ,
'=================================================='
120 WRITE(*,*)
' This the POINCARE puncture code '
121 WRITE(*,*)
' ', trim(banner),
' Last update: ',
123 WRITE(*,
'(" Runnning on ",i5," processors")') numprocs
125 WRITE(*,*)
' Please report problems to: ',
126 &
' Don Spong (spongda@ornl.gov)'
127 & ,
' or Raul Sanchez (sanchezferlr@ornl.gov).'
128 WRITE(*,*)
'--------------------------------------------------'
129 & ,
'--------------------------------------------------'
135 steps = 10; num_orbs = 10; scndry_steps = 50
136 nsurfs = 10; s1 = eps; s2 = 1.d0 -eps
141 IF( numargs .lt. 1 .OR. trim(arg1) ==
'-h')
THEN
144 print *,
' Run with arguments using:'
146 WRITE(*,*)
' xpoincare file transits surfaces orbts/surf'
147 & ,
' steps/period inner-surf(0->1) outer-surf(0->1) '
148 & ,
' type cross-section (0->360)'
150 print *,
' - FILE is the BFIELD file produced by SIESTA'
151 print *,
' - transits are the number orbit transits (tor/pol)'
152 print *,
' - steps/period are the steps used by integrator'
153 print *,
' - inner-surf, outer-surf must be between 0 and 1.'
154 print *,
' - type = poloidal or toroidal, to choose ind. var.'
155 print *,
' - choose type = toroidal if BPHI nonnegative.'
156 print *,
' - choose type = poloidal if BPHI =0 somewhere,'
157 print *,
' and BTHETA always nonnegative.'
158 print *,
' - cross-section = angle (deg) where puncture done.'
160 WRITE(*,*)
' Or run with arguments:'
162 WRITE(*,*)
' xpoincare file test_splines'
164 WRITE(*,*)
' to test splines quality with data from FILE.'
166 WRITE(*,*)
'=================================================='
167 & ,
'=================================================='
170 ELSE IF (numargs == 2 .AND. trim(arg2) ==
"test_splines")
THEN
171 l_test_splines = .true.
173 DO iargs = 1, numargs
174 IF (iargs == 1)
CALL getarg(1, arg1)
175 IF (iargs == 2)
CALL getarg(2, arg2)
176 IF (iargs == 3)
CALL getarg(3, arg3)
177 IF (iargs == 4)
CALL getarg(4, arg4)
178 IF (iargs == 5)
CALL getarg(5, arg5)
179 IF (iargs == 6)
CALL getarg(6, arg6)
180 IF (iargs == 7)
CALL getarg(7, arg7)
181 IF (iargs == 8)
CALL getarg(8, arg8)
182 IF (iargs == 9)
CALL getarg(9, arg9)
184 DO iargs = numargs+1,9
185 IF (iargs == 2) arg2 =
"100"
186 IF (iargs == 3) arg3 =
"50"
187 IF (iargs == 4) arg4 =
"12"
188 IF (iargs == 5) arg5 =
"40"
189 IF (iargs == 6) arg6 =
"0.05"
190 IF (iargs == 7) arg7 =
"0.95"
191 IF (iargs == 8) arg8 =
"toroidal"
192 IF (iargs == 9) arg9 =
"0"
197 read(arg2,
'(i6)') steps
198 read(arg3,
'(i6)') nsurfs
199 read(arg4,
'(i6)') num_orbs
200 read(arg5,
'(i6)') scndry_steps
201 read(arg6,
'(f8.4)') s1
202 read(arg7,
'(f8.4)') s2
208 IF (s1 == s2) nsurfs = 1
210 CALL tolower(type_in)
212 angle = angle*(twopi/360.d0)
213 angle = mod(angle, twopi)
214 IF (angle < 0.d0) angle = twopi + angle
215 IF (type_in ==
'poloidal')
THEN
216 theta_puncture = angle
218 WRITE(*,
'(a,1p,e10.4,a)')
219 &
' Poloidal cross section done at angle: ', angle,
' rads.'
221 ELSE IF (type_in ==
'toroidal')
THEN
224 WRITE(*,
'(2x,a,1p,e10.4,a)')
225 &
'Toroidal cross section done at angle: ', angle,
' rads.'
231 CALL spline_fields(arg1)
232 IF (l_test_splines)
THEN
235 WRITE(*,*)
' Splines tested.'
238 WRITE(*,
'(a15, f12.5, a5)')
' Total time = ', tend - tstart,
241 WRITE(*,*)
'=================================================='
242 & ,
'=================================================='
248 smin = s_knots(1) + eps
249 smax = (1.d0 - eps)*s_knots(is + ks)
251 thmax = (1.d0 - eps)*u_knots(itht + ku)
253 phimax = (1.d0 - eps) *v_knots(iphi + kv)
254 IF (s1 < smin .OR. s1 > smax) s1 = smin
255 IF (s2 < smin .OR. s2 > smax) s2 = smax
256 IF (type_in ==
'toroidal')
THEN
257 IF (angle < phimin .OR. angle > phimax)
THEN
259 WRITE(*, *)
'angle requested:', angle
260 WRITE(*, *)
'PHIMIN, PHIMAX::', phimin, phimax
262 stop
'Not enough points in toroidal spline mesh!'
264 ELSEIF (type_in ==
'poloidal')
THEN
265 IF (angle < thmin .OR. angle > thmax)
THEN
267 WRITE(*, *)
'angle requested:', angle
268 WRITE(*, *)
'THMIN, THMAX::', thmin, thmax
270 stop
'Not enough points in poloidal spline mesh!'
276 WRITE(*,*)
'--------------------------------------------------'
277 & ,
'--------------------------------------------------'
279 WRITE(*,*)
' RUN INFO:'
280 WRITE(*,*)
' ========='
282 WRITE(*,*)
' Type of integration: ', type_in
283 WRITE(*,
'(" Number of toroidal periods = ",i6,2x,
284 & "using ",i6, " steps.")') steps, scndry_steps
285 WRITE(*,
'(" Number of surfaces = ",i5)') nsurfs
286 WRITE(*,
'(" Innermost radius of surfaces = ", f8.4)') s1
287 WRITE(*,
'(" Outermost radius of surfaces = ", f8.4)') s2
288 WRITE(*,
'(" Number of orbits per surface = ",i5)') num_orbs
290 local_num_orbs = nsurfs*num_orbs/numprocs
291 norbs_tot = nsurfs*num_orbs
292 num_eqns = 2*local_num_orbs; norbs = num_eqns/2
293 IF(numprocs .gt. norbs_tot)
THEN
295 WRITE(*,
'("*** More processors (",i5,") than field lines ("
296 & ,i5,")***")') numprocs,norbs_tot
301 IF(numprocs*int(norbs_tot/numprocs) .ne. norbs_tot)
THEN
303 WRITE(*,
'("*** Number of processors (",i5,
304 & ") does not divide evenly into number of field lines ("
305 & ,i5,")***")') numprocs,norbs_tot
310 ALLOCATE(start_points(norbs_tot,2), stat=istat)
311 IF (istat .NE. 0) stop
'Allocation error'
312 ALLOCATE(theta_nb_tot(norbs_tot), stat=istat)
313 IF (istat .NE. 0) stop
'Allocation error'
314 ALLOCATE(phi_nb_tot(norbs_tot), stat=istat)
315 IF (istat .NE. 0) stop
'Allocation error'
316 ALLOCATE(s_nb_tot(norbs_tot), stat=istat)
317 IF (istat .NE. 0) stop
'Allocation error'
318 ALLOCATE(r_s_nb_tot(norbs_tot), stat=istat)
319 IF (istat .NE. 0) stop
'Allocation error'
320 ALLOCATE(z_s_nb_tot(norbs_tot), stat=istat)
321 IF (istat .NE. 0) stop
'Allocation error'
323 WRITE(*,
'(" Total number of orbits = ", i6)') norbs
324 WRITE(*,
'(" Number equations solved by LSODE = ", i6)') num_eqns
326 WRITE(*,*)
'--------------------------------------------------'
327 & ,
'--------------------------------------------------'
332 ilen = len(trim(arg1))
333 IF (arg1(ilen-3:ilen) ==
'.dat' .OR.
334 & arg1(ilen-3:ilen) ==
'.txt') i_truncate = 1
335 IF (i_truncate == 0)
THEN
336 outfile = arg1(1:ilen)//
'_puncture_'//trim(type_in)//
'.dat'
338 outfile = arg1(1:ilen-4)//
'_puncture_'//trim(type_in)//
'.dat'
341 INQUIRE(file=trim(outfile), exist= l_ex)
343 OPEN(unit = 21, file = trim(outfile), status =
"old"
344 & , access =
"append")
346 OPEN(unit = 21, file = trim(outfile), status =
"new")
348 IF (type_in ==
'poloidal')
THEN
349 WRITE(21,*)
" & phi s r phi"
350 ELSEIF (type_in ==
'toroidal')
THEN
351 WRITE(21,*)
" & tht s r z"
363 start_points(icount,1) = s1 + (s2-s1)*real(j-1, kind=rprec)/
364 & real(nsurfs-1, kind=rprec)
366 start_points(icount,1) = s1
368 start_points(icount,2) = twopi*real(i-1, kind=rprec)/
369 & real(num_orbs, kind=rprec)
375 DO i = myid*local_num_orbs+1,(myid+1)*local_num_orbs
377 y(2*icount-1) = start_points(i,1)
378 y(2*icount) = start_points(i,2)
382 WRITE(*,*)
' Starting integration....'
386 delta = twopi/scndry_steps
388 call mpi_barrier(mpi_comm_world,ierr_mpi)
390 DO it = 1, steps*scndry_steps
391 IF(mod(it,scndry_steps) == 0)
THEN
393 IF (type_in ==
'poloidal')
394 &
WRITE(*,*)
' -> Poloidal transit ',
395 & it/scndry_steps,
' completed'
396 IF (type_in ==
'toroidal')
397 &
WRITE(*,*)
' -> Toroidal transit ',
398 & it/scndry_steps,
' completed'
402 ang_out = ang_in + delta
403 rwork(5) = delta; iwork(6) = 5000
404 istate = 1; itol = 1; itask = 1; iopt = 0; jt = 10
406 IF (type_in ==
'poloidal')
THEN
407 CALL lsode(rt_hand_side_dtheta, num_eqns, y, ang_in, ang_out,
408 & itol, relerr, abserr, itask, istate, iopt, rwork, lrw,
409 & iwork, liw, jacobian, jt)
410 ELSEIF (type_in ==
'toroidal')
THEN
411 CALL lsode(rt_hand_side_dphi, num_eqns, y, ang_in, ang_out,
412 & itol, relerr, abserr, itask, istate, iopt, rwork, lrw,
413 & iwork, liw, jacobian, jt)
419 IF (istate == -1)
THEN
420 WRITE(*,*)
' Excess work. Wrong JT?'
421 WRITE(*,*)
' JT = 10. Non-stiff'
422 WRITE(*,*)
' JT = 21-25. Stiff. May need JAC.'
423 ELSEIF (istate == -2)
THEN
424 WRITE(*,*)
' Excess accuracy requested'
425 ELSEIF (istate == -3)
THEN
426 WRITE(*,*)
' Illegal input'
427 ELSEIF (istate == -4)
THEN
428 WRITE(*,*)
' Repeated error test failures'
429 ELSEIF (istate == -5)
THEN
430 WRITE(*,*)
' Repeated convergence failures'
431 WRITE(*,*)
' Maybe bad Jacobian?'
432 ELSEIF (istate == -6)
THEN
433 WRITE(*,*)
' Error weight became zero!'
435 WRITE(*,*)
'ANGLE done so far:', ang_in
438 IF (type_in ==
'poloidal')
THEN
440 s_test = y(2*i-1); phi_test = y(2*i)
441 CALL reset_coords(s_test, rdum, phi_test)
442 y(2*i-1) = s_test; y(2*i)= phi_test
444 ELSEIF (type_in ==
'toroidal')
THEN
446 s_test = y(2*i-1); theta_test = y(2*i)
447 CALL reset_coords(s_test, theta_test, rdum)
448 y(2*i-1) = s_test; y(2*i)= theta_test
452 IF (mod(it, scndry_steps) == 0)
THEN
454 IF (type_in ==
'poloidal')
THEN
457 theta_nb(i) = theta_puncture
461 CALL dbs3vd(0, 0, 0, norbs, s_nb, theta_nb, phi_nb,
462 & ks, ku, kv, s_knots, u_knots, v_knots, is, itht, iphi,
463 & r_coef, r_s_nb, is_uniformx, is_uniformy, is_uniformz )
466 call mpi_barrier(mpi_comm_world,ierr_mpi)
467 call mpi_gather(phi_nb,norbs,mpi_real8,
468 > phi_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
469 call mpi_gather(s_nb,norbs,mpi_real8,
470 > s_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
471 call mpi_gather(r_s_nb,norbs,mpi_real8,
472 > r_s_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
474 phi_nb_tot(:) = phi_nb(:)
475 s_nb_tot(:) = s_nb(:)
476 r_s_nb_tot(:) = r_s_nb(:)
479 call mpi_barrier(mpi_comm_world,ierr_mpi)
485 WRITE(21,
'(e15.7, 3(3x, e15.7))') phi_nb_tot(i),
486 & s_nb_tot(i), r_s_nb_tot(i), phi_nb_tot(i)
490 ELSEIF (type_in ==
'toroidal')
THEN
495 phi_nb(i) = phi_puncture
497 CALL dbs3vd(0, 0, 0, norbs, s_nb, theta_nb, phi_nb,
498 & ks, ku, kv, s_knots, u_knots, v_knots, is, itht, iphi,
499 & r_coef, r_s_nb, is_uniformx, is_uniformy, is_uniformz )
501 CALL dbs3vd(0, 0, 0, norbs, s_nb, theta_nb, phi_nb,
502 & ks, ku, kv, s_knots, u_knots, v_knots, is, itht, iphi,
503 & z_coef, z_s_nb, is_uniformx, is_uniformy, is_uniformz )
506 call mpi_barrier(mpi_comm_world,ierr_mpi)
507 call mpi_gather(theta_nb,norbs,mpi_real8,
508 > theta_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
509 call mpi_gather(s_nb,norbs,mpi_real8,
510 > s_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
511 call mpi_gather(r_s_nb,norbs,mpi_real8,
512 > r_s_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
513 call mpi_gather(z_s_nb,norbs,mpi_real8,
514 > z_s_nb_tot,norbs,mpi_real8,0,mpi_comm_world,ierr_mpi)
516 theta_nb_tot(:) = theta_nb(:)
517 s_nb_tot(:) = s_nb(:)
518 r_s_nb_tot(:) = r_s_nb(:)
519 z_s_nb_tot(:) = z_s_nb(:)
522 call mpi_barrier(mpi_comm_world,ierr_mpi)
526 WRITE(21,
'(e15.7, 3(3x, e15.7))') theta_nb_tot(i),
527 & s_nb_tot(i), r_s_nb_tot(i), z_s_nb_tot(i)
540 call mpi_barrier(mpi_comm_world,ierr_mpi)
542 DEALLOCATE(s_nb_tot,phi_nb_tot,theta_nb_tot,r_s_nb_tot,
543 & z_s_nb_tot,start_points)
549 WRITE(*,*)
' .... completed.'
551 WRITE(*,
'(a15, f12.5, a5)')
' Total time = ', tend - tstart,
554 WRITE(*,*)
'=================================================='
555 & ,
'=================================================='
559 call mpi_finalize(ierr_mpi)