| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | module orbit_fo_field | ||
| 2 | ! Field provider for the full-orbit (FO) Boris pusher on the production | ||
| 3 | ! Boozer/chartmap chart. The chartmap reference coordinate is rho = sqrt(s) | ||
| 4 | ! with the same angles as the production field_can_boozer chart, so the libneo | ||
| 5 | ! chartmap geometry (reference_coordinates%ref_coords) is native. The Boozer | ||
| 6 | ! flux potential A_theta(s), A_phi(s), |B| and the field |B|-derivatives come | ||
| 7 | ! from field_can, reparametrized from s = rho^2 by the radial chain rule | ||
| 8 | ! dF/drho = 2 rho dF/ds; the angular derivatives are unchanged. | ||
| 9 | use, intrinsic :: iso_fortran_env, only: dp => real64 | ||
| 10 | implicit none | ||
| 11 | private | ||
| 12 | |||
| 13 | public :: fo_eval_field, fo_eval_reference_field, & | ||
| 14 | fo_reference_field_available | ||
| 15 | |||
| 16 | contains | ||
| 17 | |||
| 18 | 1421438 | logical function fo_reference_field_available() | |
| 19 | use magfie_sub, only: has_magfie_refcoords_field | ||
| 20 | |||
| 21 | 1 | fo_reference_field_available = has_magfie_refcoords_field() | |
| 22 | 1 | end function fo_reference_field_available | |
| 23 | |||
| 24 | 13 | subroutine fo_eval_reference_field(u, hcov, Bmod, status) | |
| 25 | 1 | use magfie_sub, only: evaluate_magfie_refcoords_field | |
| 26 | real(dp), intent(in) :: u(3) | ||
| 27 | real(dp), intent(out) :: hcov(3), Bmod | ||
| 28 | integer, intent(out) :: status | ||
| 29 | real(dp) :: Acov(3) | ||
| 30 | |||
| 31 | 13 | call evaluate_magfie_refcoords_field(u, Acov, hcov, Bmod, status) | |
| 32 | 13 | end subroutine fo_eval_reference_field | |
| 33 | |||
| 34 | ! Production Boozer field at u=(rho,theta_B,phi_B), reparametrized from | ||
| 35 | ! field_can(s=rho^2). field_can returns covariant A_theta,A_phi (A_s=0), | ||
| 36 | ! covariant h_theta,h_phi (h_s=0), |B| and the s-derivatives. Only the radial | ||
| 37 | ! coordinate differs: F(rho)=F(s(rho)), dF/drho = 2 rho dF/ds; angular | ||
| 38 | ! derivatives are unchanged. dA(i,k)=dA_i/du_k carries the same chain rule on | ||
| 39 | ! its radial column. | ||
| 40 | 1421437 | subroutine fo_eval_field(u, Acov, dA, Bmod, dBmod, hcov) | |
| 41 | 13 | use field_can_mod, only: eval_field => evaluate, field_can_t | |
| 42 | real(dp), intent(in) :: u(3) | ||
| 43 | real(dp), intent(out) :: Acov(3), dA(3,3), Bmod, dBmod(3), hcov(3) | ||
| 44 | type(field_can_t) :: f | ||
| 45 | real(dp) :: rho, ds_drho | ||
| 46 | |||
| 47 | 1421437 | rho = u(1) | |
| 48 | 1421437 | ds_drho = 2.0_dp*rho ! ds/drho = 2 rho (s = rho^2); dF/drho = ds/drho dF/ds | |
| 49 | |||
| 50 | 1421437 | call eval_field(f, rho*rho, u(2), u(3), 0) | |
| 51 | |||
| 52 |
2/2✓ Branch 0 taken 4264311 times.
✓ Branch 1 taken 1421437 times.
|
5685748 | Acov = [0.0_dp, f%Ath, f%Aph] |
| 53 |
2/2✓ Branch 0 taken 4264311 times.
✓ Branch 1 taken 1421437 times.
|
5685748 | hcov = [0.0_dp, f%hth, f%hph] |
| 54 | 1421437 | Bmod = f%Bmod | |
| 55 | |||
| 56 | ! dA(i,k) = dA_i/du_k. A_s = 0 (row 1 all zero). Rows 2,3 (A_theta, A_phi): | ||
| 57 | ! radial column k=1 scales by ds/drho; angular columns unchanged. | ||
| 58 | 1421437 | dA = 0.0_dp | |
| 59 | 1421437 | dA(2,1) = f%dAth(1)*ds_drho | |
| 60 | 1421437 | dA(2,2) = f%dAth(2) | |
| 61 | 1421437 | dA(2,3) = f%dAth(3) | |
| 62 | 1421437 | dA(3,1) = f%dAph(1)*ds_drho | |
| 63 | 1421437 | dA(3,2) = f%dAph(2) | |
| 64 | 1421437 | dA(3,3) = f%dAph(3) | |
| 65 | |||
| 66 | ! d|B|/du_k: radial column scales, angular columns unchanged. | ||
| 67 | 1421437 | dBmod(1) = f%dBmod(1)*ds_drho | |
| 68 | 1421437 | dBmod(2) = f%dBmod(2) | |
| 69 | 1421437 | dBmod(3) = f%dBmod(3) | |
| 70 |
4/4✓ Branch 0 taken 1421437 times.
✓ Branch 1 taken 4264311 times.
✓ Branch 2 taken 8528622 times.
✓ Branch 3 taken 1421437 times.
|
17057244 | end subroutine fo_eval_field |
| 71 | |||
| 72 | end module orbit_fo_field | ||
| 73 |