V3FIT
biotsavart.f
1  MODULE biotsavart
2  USE stel_kinds
3  USE bsc_t
4  IMPLICIT NONE
5 !-----------------------------------------------
6 ! L o c a l P a r a m e t e r s
7 !-----------------------------------------------
8  REAL(rprec), PARAMETER :: zero = 0
9 !-----------------------------------------------
10 ! L o c a l V a r i a b l e s
11 !-----------------------------------------------
12  INTEGER :: nfp_bs
13  TYPE (bsc_coil), POINTER :: single_coil => null()
14  TYPE (bsc_coilcoll), DIMENSION(:), ALLOCATABLE, TARGET ::
15  & coil_group
16 
17 !
18 ! coil_group Collection of coils, used to store coils by group id
19 ! single coil A single coil
20 !
21  CONTAINS
22 
23 !----------------------------------------------------------------------
24 !*******************************************************************************
25 !----------------------------------------------------------------------
26 
27  SUBROUTINE initialize_biotsavart (extcur_in, extension,
28  1 xpt, scaled)
29  IMPLICIT NONE
30 !-----------------------------------------------
31 ! D u m m y A r g u m e n t s
32 !-----------------------------------------------
33  REAL(rprec), INTENT(in), DIMENSION(:) :: extcur_in
34  REAL(rprec), DIMENSION(:,:), OPTIONAL :: xpt
35  LOGICAL, OPTIONAL :: scaled
36  CHARACTER(LEN=*), OPTIONAL :: extension
37 !-----------------------------------------------
38 ! L o c a l V a r i a b l e s
39 !-----------------------------------------------
40  TYPE(bsc_coil) :: coil_temp
41  INTEGER :: istat
42  INTEGER :: nextcur, ig, nc
43  REAL(rprec) :: current, current_first
44  CHARACTER(len=200) :: coil_file
45  LOGICAL :: scaled_or_raw
46 !-----------------------------------------------
47  scaled_or_raw = .true.
48  IF (PRESENT(scaled)) scaled_or_raw = scaled
49 
50  IF (PRESENT(extension)) THEN
51 ! Parse coils.extension file and initialize bsc routines
52  coil_file = 'coils.' // trim(extension)
53  CALL parse_coils_file (trim(coil_file))
54 ! Set currents in coils in each group
55 ! Note: current_first is read in from "coil_file"
56  nextcur = SIZE(coil_group)
57  IF (scaled_or_raw) THEN
58  DO ig = 1, nextcur
59  DO nc = 1, coil_group(ig) % ncoil
60  current = coil_group(ig) % coils(nc) % current
61  IF (nc .eq. 1) current_first = current
62  IF (current_first .ne. zero)
63  1 coil_group(ig) % coils(nc) % current =
64  1 (current/current_first)*extcur_in(ig)
65  END DO
66  END DO
67  END IF
68 
69  ELSE IF (PRESENT(xpt)) THEN
70 ! Initialize biotsavart MODULE
71  nextcur = 1
72  CALL cleanup_biotsavart
73 ! Create the coil (DO NOT CLOSE IT!)
74  nc = SIZE(xpt,2)
75  ALLOCATE (single_coil)
76  CALL bsc_construct(single_coil,'fil_loop','','', &
77  & extcur_in(1),xpt(1:3,1:nc))
78 
79  ELSE
80  stop 'Fatal: initialize_bs: xpt or extension must be specified'
81  END IF
82 
83  END SUBROUTINE initialize_biotsavart
84 
85 !----------------------------------------------------------------------
86 !*******************************************************************************
87 !----------------------------------------------------------------------
88 
89  SUBROUTINE parse_coils_file (coil_file, lgrps)
90  USE safe_open_mod
91  IMPLICIT NONE
92 !-----------------------------------------------
93 ! D u m m y A r g u m e n t s
94 !-----------------------------------------------
95  CHARACTER(LEN=*) :: coil_file
96  LOGICAL, OPTIONAL :: lgrps
97 !-----------------------------------------------
98 ! L o c a l P a r a m e t e r s
99 !-----------------------------------------------
100  INTEGER, PARAMETER :: iou_coil0=22
101  INTEGER, PARAMETER :: maxgroups = 1000
102 !-----------------------------------------------
103 ! L o c a l V a r i a b l e s
104 !-----------------------------------------------
105  INTEGER :: istat, i_line
106  INTEGER, DIMENSION(:) :: ngroup(maxgroups)
107  INTEGER :: nmaxnodes, iou_coil, nextcur
108  INTEGER :: n_line_start_string, n_line_skip
109  CHARACTER(LEN=200) :: line, group, line_lc
110  CHARACTER(LEN=28) :: start_string = '** coils_dot_starts_below **'
111  LOGICAL :: local_lgrps
112 !-----------------------------------------------
113 !
114 ! OPEN COILS.EXT (COIL_FILE)
115 !
116  iou_coil = iou_coil0
117  CALL safe_open(iou_coil, istat, trim(coil_file), 'old', &
118  & 'formatted')
119  IF (istat .ne. 0) stop 'Error opening input coil file'
120 
121 ! start_string added JDH, April 2011.
122 ! Find the line number where the start_string occurs (if at all)
123 ! Leave the file positioned at the line after the start_string
124 ! (or at the beginning of the file, if the start_string does not occur)
125  i_line = 0
126  n_line_start_string = 0
127  read_loop : DO
128  i_line = i_line + 1
129  READ(iou_coil,'(a)',END = 100, IOSTAT=istat) line
130  IF (istat .ne. 0) THEN
131  WRITE(6,*) 'Problem in parse_coils_file. istat =',istat
132  WRITE(6,*) ' Line number is ', i_line
133  WRITE(6,*) line
134  stop
135  END IF
136  line_lc = line
137  CALL tolower(line_lc)
138  istat = index(line, start_string)
139  IF (istat .eq. 0) THEN ! did not find start_string
140  cycle
141  ELSE ! did find start_string
142  n_line_start_string = i_line
143  WRITE(6,*) 'Found start_string: ', start_string
144  WRITE(6,*) ' in line ', n_line_start_string
145  EXIT
146  ENDIF
147  END DO read_loop
148 
149 100 IF (n_line_start_string .eq. 0) THEN
150  rewind(iou_coil, iostat=istat)
151  IF (istat .ne. 0) THEN
152  WRITE(6,*) 'Problem 2 in parse_coils_file. istat =',istat
153  stop
154  END IF
155  END IF
156 ! Define number of lines to skip on subsequent re-reading
157  n_line_skip = 3 + n_line_start_string
158 
159 ! READ IN NUMBER OF FIELD PERIODS
160  READ (iou_coil, '(a)' , iostat=istat) line
161  istat = index(line, 'periods')
162  IF (istat .eq. 0) &
163  & stop 'First line of coils file must contain # periods'
164  READ (line, *, iostat=istat) group, nfp_bs
165 
166  local_lgrps = .false.
167  IF (PRESENT(lgrps)) local_lgrps = lgrps
168 
169 ! First pass through the input file, to find out how many coil groups,
170 ! and the maximum number of nodes in ANY one coil.
171  CALL read_coils_pass1(iou_coil, nextcur, nmaxnodes, ngroup, &
172  & local_lgrps, n_line_skip)
173 
174 ! Now that we know how many coil groups there are, ALLOCATE
175 ! the bsc_coilcoll array.
176  IF (nextcur .gt. 0) THEN
177  CALL cleanup_biotsavart
178  ALLOCATE (coil_group(nextcur), stat=istat)
179  IF (istat .ne. 0) stop 'ERROR ALLOCATION COIL COLLECTION'
180  ELSE
181  WRITE(*,*) 'number coilgroups = ',nextcur,' <= 0 '
182  stop
183  END IF
184 
185 ! Second pass through the file. Read ALL the coils, and store
186 ! them in the appropriate groups.
187  CALL read_coils_pass2(iou_coil, nmaxnodes, coil_group, ngroup, &
188  & local_lgrps, n_line_skip)
189 
190  END SUBROUTINE parse_coils_file
191 
192 !----------------------------------------------------------------------
193 !*******************************************************************************
194 !----------------------------------------------------------------------
195 
196  SUBROUTINE read_coils_pass1 (iou, n_coilgroups, nmaxnodes, ngroup, &
197  & lgrps, n_skip)
198 ! Subroutine to do a first pass read of the "coils" file. The purpose is
199 ! to find the number of coil groups, and the maximum number of
200 ! nodes in ANY one coil.
201 
202  IMPLICIT NONE
203 !-----------------------------------------------
204 ! D u m m y A r g u m e n t s
205 !-----------------------------------------------
206  INTEGER, INTENT(in) :: iou, n_skip
207  INTEGER, INTENT(out) :: n_coilgroups, nmaxnodes
208  INTEGER, DIMENSION(:), INTENT(out) :: ngroup
209  LOGICAL, INTENT(in) :: lgrps
210 
211 ! iou Default integer - Fortran I/O unit number
212 ! n_coilgroups Number of external current coil groups.
213 ! (In MAKEGRID this is nextcur. Read as n_extcur, not next_cur)
214 ! n_skip Number of line to skip at the beginning of the file
215 ! nmaxnodes Maximum number of nodes in ANY one coil
216 ! ngroup Array of coil group numbers
217 ! igroup, when lgrps is False
218 ! Sequential, when lgrps is True
219 ! lgrps Logical.
220 ! True - Each separate coil is stored in its own coil group
221 ! False - Placement into coil groups determined by integer igroup
222 ! read from the coils. file
223 !
224 !-----------------------------------------------
225 ! L o c a l V a r i a b l e s
226 !-----------------------------------------------
227  CHARACTER(200) :: line
228  CHARACTER(100) :: group_id
229  REAL(rprec) :: xw, yw, zw
230  REAL(rprec) :: currin
231  INTEGER :: i, igroup, inodes
232  INTEGER :: istat
233  LOGICAL :: lparsed
234 
235 ! line Used for reading (and rereading) a line from the input file
236 ! group_id Identifier of an external current coil group
237 ! In MAKEGRID, this is variable group
238 ! xw, yw, zw Scalars used for parsing Cartisian coordinates of wires
239 ! currin current
240 ! igroup Integer, number of an external current coil group
241 ! inodes Integer, counter for the number of nodes in a coil
242 ! istat Default integer, for I/O status
243 ! lparsed Indicates previous line was parsed (used in case "end" statement missing)
244 !-----------------------------------------------
245 
246 ! Start of Executable Code
247 ! Read in first n_skip lines
248  rewind(iou, iostat=istat)
249  DO i = 1,n_skip
250  READ(iou,'(a)') line
251  END DO
252 
253 ! Initialize counters
254  inodes = 0
255  nmaxnodes = 0
256  n_coilgroups = 0
257  ngroup(:) = -1
258 
259 ! Loop to read in the rest of the lines from the file
260 ! Last line of the file should be just 'end'.
261  read_loop : DO
262  READ(iou,'(a)',END = 100, IOSTAT=istat) line
263  IF (istat .ne. 0) THEN
264  WRITE(6,*) 'Problem in read_coils_pass1. istat =',istat
265  WRITE(6,*) line
266  stop
267  END IF
268 
269  IF (line(1:3) .eq. 'end') EXIT
270  inodes = inodes + 1
271 
272 ! Reread the line, assuming igroup and group_id are there.
273 ! For most of the file, they won't be there, and istat will be nonzero
274 ! But, when igroup and group_id are there, istat will be zero.
275 ! This is the indication of the END of a coil
276 !
277 ! Note: IGROUP numbering may NOT be contiguous in file NOR does it
278 ! have to be sequential (1,2,3). Thus, igroup = 55,11,101,...
279 ! MIGHT occur in file and should be accounted for in this logic.
280 
281  READ(line,*,iostat=istat) xw, yw, zw, currin, igroup, group_id
282  lparsed = (istat .eq. 0)
283  IF (lparsed) THEN
284  i = minval(abs(igroup - ngroup(:)))
285  IF (i.ne.0 .or. lgrps) THEN !ADD NEW GROUP AND STORE IN NGROUP
286  n_coilgroups = n_coilgroups + 1
287  IF (n_coilgroups .gt. SIZE(ngroup)) THEN
288  stop ' read_coils_pass1: coil groups > SIZE(ngroup)'
289  ENDIF
290  IF (lgrps) THEN
291  ngroup(n_coilgroups) = n_coilgroups
292  ELSE ! lgrps is False
293  ngroup(n_coilgroups) = igroup
294  END IF
295  END IF
296  nmaxnodes = max(nmaxnodes,inodes)
297  inodes = 0
298  END IF
299  END DO read_loop
300 
301 !
302 ! CATCH OLD STYLE (ONE BIG COIL) FILE
303 !
304  IF (nmaxnodes .eq. 0) THEN
305  nmaxnodes = inodes
306  n_coilgroups = 1
307  ngroup(1) = 1
308  END IF
309 
310  RETURN
311 
312 100 IF (.not. lparsed) THEN
313  WRITE(6,*) 'Problems in read_coils_pass1'
314  WRITE(6,*) 'EOF reached before END'
315  WRITE(6,*) 'Make sure last line of file is "end"'
316  END IF
317 
318  END SUBROUTINE read_coils_pass1
319 !----------------------------------------------------------------------
320 !*******************************************************************************
321 !----------------------------------------------------------------------
322 
323  SUBROUTINE read_coils_pass2 (iou, nmaxnodes, coil_group, ngroup, &
324  & lgrps, n_skip)
325 ! Subroutine to do a second pass read of the coils file. The data is then
326 ! used tocreate a filamentary loop coil (fil_loop). The fil_loop is then appended
327 ! to the correct coil group.
328 
329  IMPLICIT NONE
330 !-----------------------------------------------
331 ! D u m m y A r g u m e n t s
332 !-----------------------------------------------
333  INTEGER, INTENT(in) :: iou, n_skip
334  INTEGER, INTENT(in) :: nmaxnodes
335  INTEGER, DIMENSION(:), INTENT(in) :: ngroup
336  TYPE (bsc_coilcoll), DIMENSION(:), INTENT(inout) :: coil_group
337  LOGICAL, INTENT(in) :: lgrps
338 
339 ! iou Default Integer - Fortran I/O unit number
340 ! nmaxnodes Maximum number of nodes in ANY one coil
341 ! ngroup Array of integer coil group numbers
342 ! igroup, when lgrps is False
343 ! Sequential, when lgrps is True
344 ! n_skip Number of line to skip at the beginning of the file
345 ! coil_group Array of special type from module bsc. Each element in the array
346 ! stores a coil collection
347 ! lgrps Logical.
348 ! True - Each separate coil is stored in its own coil group
349 ! False - Placement into coil groups determined by integer igroup
350 ! read from the coils. file
351 !
352 !-----------------------------------------------
353 ! L o c a l V a r i a b l e s
354 !-----------------------------------------------
355  INTEGER, DIMENSION(:) :: index1(1)
356  INTEGER :: istat
357  INTEGER :: n_coilgroups, id_group
358  INTEGER :: i, igroup, inodes, nnod, icoil
359  TYPE(bsc_coil) :: coil_temp
360  REAL(rprec), DIMENSION(3,nmaxnodes) :: xnod_in
361  REAL(rprec) :: currin, currin_first
362  REAL(rprec) :: this_rcirc
363  REAL(rprec), DIMENSION(3) :: this_xcent, this_enhat
364  CHARACTER :: line*200, group_id*100
365  CHARACTER(len=LEN(coil_group(1)%s_name)) :: s_name
366  CHARACTER(len=LEN(coil_group(1)%l_name)) :: l_name
367  LOGICAL :: lparsed
368 
369 ! index1 Default integer array - result from MINLOC
370 ! istat Default integer, for I/O status
371 ! n_coilgroups Number of external current coil groups.
372 ! (In MAKEGRID this is nextcur. Read as n_extcur, not next_cur)
373 ! id_group sequential id (from ngroup array) for coil group igroup
374 ! igroup number of an externalcurrent coil group
375 ! inodes counter for the number of nodes in a coil
376 ! nnod number of nodes in a coil.
377 ! coil_temp Special type from module bsc. Stores a single coil.
378 ! xnod_in Real array to store coil nodes as they're being read in.
379 ! currin current
380 ! currin_first current of first node in a coil.
381 ! line CHARACTER, for reading (and rereading) a line from the input file
382 ! group_id CHARACTER, identifier of an external current coil group
383 ! In MAKEGRID, this is variable group
384 !-----------------------------------------------
385 ! Find out how many coil groups there are
386  n_coilgroups = SIZE(coil_group)
387 
388 ! Create the coil collections
389  DO i = 1,n_coilgroups
390  WRITE(l_name,*) 'i = ',i
391  CALL bsc_construct(coil_group(i),'boring id',l_name)
392  END DO
393 
394 ! Rewind the file
395  rewind(iou, iostat=istat)
396 
397 ! Read in first n_skip lines
398  DO i = 1,n_skip
399  READ(iou,'(a)') line
400  END DO
401 
402 ! Initialize counters
403  inodes = 0
404  id_group = 0
405 
406 ! Loop to read in the rest of the lines from the file
407 ! Last line of the file should be just 'end'.
408  read_loop : DO
409  READ(iou,'(a)',END = 100) line
410  IF (line(1:3) .eq. 'end') EXIT
411  inodes = inodes + 1
412 
413 ! Reread the line
414  READ(line,*,iostat=istat) xnod_in(1:3,inodes), currin
415 
416 ! Save the current from the first node
417  IF (inodes .eq. 1) currin_first = currin
418 
419 ! Reread the line, assuming igroup and group_id are there.
420 ! For most of the file, they won't be there, and istat will be nonzero
421 ! But, when igroup and group_id are there, istat will be zero.
422 ! This is the indication of the END of a coil
423  READ(line,*,iostat=istat) xnod_in(1:3,inodes), currin, &
424  & igroup, group_id
425  lparsed = (istat .eq. 0)
426  IF (lparsed) THEN
427 
428 ! JDH 2007-09-03. Modified below to make consistent with module coils_dot
429 ! behavior. In particular, interpretation of a single node coils is as
430 ! a circular coil. short name for the coil is unchanged from previous makegrid.
431 ! Find sequential group id no. for this igroup value
432  IF (lgrps) THEN
433  id_group = id_group + 1
434  ELSE
435  index1 = minloc(abs(igroup - ngroup(:)))
436  id_group = index1(1)
437  IF (igroup .ne. ngroup(id_group)) &
438  & stop 'ID_GROUP != IGROUP in coils_dot_pass2'
439  END IF
440 
441 ! Define a short name for the coil
442  icoil = coil_group(id_group) % ncoil + 1
443  WRITE(s_name, '(a4,i5.5)') 'ID #', icoil
444 
445 ! Various cases, depending on how many lines have been read in
446  SELECT CASE (inodes)
447 
448  CASE (1) ! Circular coil
449  this_xcent(1:3) = (/ zero, zero, xnod_in(3,1) /)
450  this_enhat(1:3) = (/ zero, zero, 1.0_rprec /)
451  this_rcirc = xnod_in(1,1)
452  CALL bsc_construct(coil_temp,'fil_circ',s_name,'', &
453  & currin_first, rcirc = this_rcirc, &
454  & xcent = this_xcent(1:3),enhat = this_enhat(1:3))
455 
456  CASE (2) ! Two point filament - treat like infinite straight coil
457  nnod = inodes
458  CALL bsc_construct(coil_temp,'fil_loop',s_name,'', &
459  & currin_first,xnod_in(1:3,1:nnod))
460 
461  CASE DEFAULT ! Filamentary loop
462 ! Last point is supposed to be identical with the
463 ! first point of the coil. bsc_construct assumes that the
464 ! coil is not yet closed, so don't include the last point
465  nnod = inodes - 1
466  CALL bsc_construct(coil_temp,'fil_loop',s_name,'', &
467  & currin_first,xnod_in(1:3,1:nnod))
468 
469  END SELECT
470 
471 ! Append the coil to the appropriate coil group
472  CALL bsc_append(coil_group(id_group),coil_temp)
473 
474 ! Save the EXTERNAL coil group identifier group_id
475  coil_group(id_group) % s_name = trim(group_id)
476  WRITE (coil_group(id_group) % l_name,'(a7,i6.6)')
477  1 ' IGROUP',igroup
478 
479 ! Reset the number of nodes to zero
480  inodes = 0
481 
482  END IF ! of istat .eq. 0 IF
483  END DO read_loop
484 
485  RETURN
486 
487 100 IF (.not. lparsed) THEN
488  WRITE(6,*) 'Problems in read_coils_pass2'
489  WRITE(6,*) 'EOF reached before END'
490  WRITE(6,*) 'Make sure last line of file is "end"'
491  END IF
492 
493  END SUBROUTINE read_coils_pass2
494 
495 !----------------------------------------------------------------------
496 !*******************************************************************************
497 !----------------------------------------------------------------------
498 
499  SUBROUTINE bfield (rp, phi, zp, br, bp, bz, ig)
500  IMPLICIT NONE
501 !-----------------------------------------------
502 ! D u m m y A r g u m e n t s
503 !-----------------------------------------------
504  INTEGER, OPTIONAL :: ig
505  REAL(rprec), INTENT(in) :: rp, phi, zp
506  REAL(rprec), INTENT(out) :: br, bp, bz
507 !-----------------------------------------------
508 ! L o c a l V a r i a b l e s
509 !-----------------------------------------------
510  INTEGER :: igroup
511  REAL :: cosp, sinp
512  REAL(rprec), DIMENSION(3) :: xpt, bvec
513 !-----------------------------------------------
514 
515 ! Convert to cartesian coordinates
516  cosp = cos(phi); sinp = sin(phi)
517  xpt(1) = rp*cosp
518  xpt(2) = rp*sinp
519  xpt(3) = zp
520 
521  igroup = 1
522  IF (PRESENT(ig)) igroup = ig
523 
524  CALL bsc_b (coil_group(igroup), xpt, bvec)
525 
526 ! Convert back to cylindrical coordinates from cartesian vector components of B
527  br = bvec(1)*cosp + bvec(2)*sinp
528  bp =-bvec(1)*sinp + bvec(2)*cosp
529  bz = bvec(3)
530 
531  END SUBROUTINE bfield
532 
533 !----------------------------------------------------------------------
534 !*******************************************************************************
535 !----------------------------------------------------------------------
536 
537  SUBROUTINE write_coils_file (extension)
538  USE safe_open_mod
539  IMPLICIT NONE
540 !-----------------------------------------------
541 ! D u m m y A r g u m e n t s
542 !-----------------------------------------------
543  CHARACTER(LEN=*) :: extension
544 !-----------------------------------------------
545 ! L o c a l V a r i a b l e s
546 !-----------------------------------------------
547  INTEGER :: cunit=30, ierr, ig, ncoils, n, nwire, iwire, nextcur
548  REAL(rprec) :: current
549  CHARACTER(len=LEN(coil_group(1)%s_name)) :: g_name
550 !-----------------------------------------------
551 !
552 ! WRITES (OR OVERWRITE) A COILS.EXT FILE BASED ON PRESENT COIL_GROUP DATA
553 !
554  CALL safe_open(cunit, ierr, 'coils.' // trim(extension),
555  1 'replace', 'formatted')
556  IF (ierr .ne. 0)stop 'Error opening coils-dot file in write_coils'
557 
558 !
559 ! WRITE CANONICAL HEADER
560 !
561  WRITE (cunit,100) nfp_bs
562  100 FORMAT("periods ",i2,/,"begin filament",/,"mirror NUL")
563 
564 !
565 ! WRITE (x, y, z, cur [,label]) INFO
566 !
567  nextcur = SIZE(coil_group)
568  DO ig = 1, nextcur
569  ncoils = coil_group(ig) % ncoil
570  g_name = coil_group(ig) % s_name
571  DO n = 1, ncoils
572  current = coil_group(ig) % coils(n) % current
573  nwire = SIZE(coil_group(ig) % coils(n) % xnod, 2)
574  IF (any(coil_group(ig) % coils(n) % xnod(:,1) .ne.
575  1 coil_group(ig) % coils(n) % xnod(:,nwire)))
576  1 print *, 'Coil did not close in WRITE_COILS_DOT for group ',
577  2 ig,' COIL ',n
578  DO iwire = 1, nwire-1
579  WRITE(cunit,'(1p,4e22.14)')
580  1 coil_group(ig) % coils(n) % xnod(:,iwire), current
581  END DO
582  WRITE(cunit,'(1p,4e22.14,i4,1x,a)')
583  1 coil_group(ig) % coils(n) % xnod(:,nwire), zero, ig,
584  2 trim(g_name)
585  END DO
586  END DO
587 
588  WRITE (cunit, '(a3)') "end"
589 
590  CLOSE (cunit)
591 
592  END SUBROUTINE write_coils_file
593 
594 !----------------------------------------------------------------------
595 !*******************************************************************************
596 !----------------------------------------------------------------------
597 
598  SUBROUTINE afield (rp, phi, zp, ar, ap, az, ig)
599  IMPLICIT NONE
600 !-----------------------------------------------
601 ! D u m m y A r g u m e n t s
602 !-----------------------------------------------
603  INTEGER, OPTIONAL :: ig
604  REAL(rprec), INTENT(in) :: rp, phi, zp
605  REAL(rprec), INTENT(out) :: ar, ap, az
606 !-----------------------------------------------
607 ! L o c a l V a r i a b l e s
608 !-----------------------------------------------
609  INTEGER :: igroup
610  REAL :: cosp, sinp
611  REAL(rprec), DIMENSION(3) :: xpt, avec
612 !-----------------------------------------------
613 
614 ! Convert to cartesian coordinates
615  cosp = cos(phi); sinp = sin(phi)
616  xpt(1) = rp*cosp
617  xpt(2) = rp*sinp
618  xpt(3) = zp
619 
620  igroup = 1
621  IF (PRESENT(ig)) igroup = ig
622 
623  CALL bsc_a (coil_group(igroup), xpt, avec)
624 
625 ! Convert back to cylindrical coordinates from cartesian vector components of A
626  ar = avec(1)*cosp + avec(2)*sinp
627  ap =-avec(1)*sinp + avec(2)*cosp
628  az = avec(3)
629 
630  END SUBROUTINE afield
631 
632 !----------------------------------------------------------------------
633 !*******************************************************************************
634 !----------------------------------------------------------------------
635 
636  SUBROUTINE cleanup_biotsavart
637  IMPLICIT NONE
638 !-----------------------------------------------
639 ! L o c a l V a r i a b l e s
640 !-----------------------------------------------
641  INTEGER :: i
642 !-----------------------------------------------
643 
644  IF (ALLOCATED(coil_group)) THEN
645  DO i = 1, SIZE(coil_group)
646  CALL bsc_destroy(coil_group(i))
647  END DO
648  DEALLOCATE(coil_group)
649  END IF
650 
651  IF (ASSOCIATED(single_coil)) THEN
652  CALL bsc_destroy(single_coil)
653  DEALLOCATE(single_coil)
654  END IF
655 
656  END SUBROUTINE cleanup_biotsavart
657 
658  END MODULE biotsavart
659 
660 !MODIFICATION HISTORY
661 !03.16.04 (SPH) Added l_name to coil_group (in read_pass2), based on original igroup in coils-dot file
662 !10.09.08 (SPH) REPLACE INTEGER(iprec) with INTEGER
663 !11.24.10 (SPH) added lparsed logical to avoid eof error message if coils file does not terminate with "end"
664 ! 2011-04-01 (JDH) Added start_string to parse_coils_file. Also, miscellaneous cleanup.
665 ! 2014-08-01 (SAL) Added afield routine (copy of bfield)
bsc_t::bsc_construct
Definition: bsc_T.f:181