halo_to_rv Subroutine

public subroutine halo_to_rv(libpoint, mu1, mu2, dist, A_z, n, t1, rv, period)

Compute the state vector from the halo orbit approximation. This will be an approximation of a halo orbit in the CR3BP system, and will need to be corrected to produce a real halo orbit.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: libpoint

Libration point number: [1,2,3]

real(kind=wp), intent(in) :: mu1

grav param for primary body [km3/s2]

real(kind=wp), intent(in) :: mu2

grav param for secondary body [km3/s2]

real(kind=wp), intent(in) :: dist

distance between bodies [km]

real(kind=wp), intent(in) :: A_z

halo z amplitude [km]

integer, intent(in) :: n

halo family: 1, 3

real(kind=wp), intent(in) :: t1

tau1 [rad]

real(kind=wp), intent(out), dimension(6) :: rv

cr3bp normalized state vector [wrt barycenter]

real(kind=wp), intent(out), optional :: period

normalized halo orbit period


Calls

proc~~halo_to_rv~~CallsGraph proc~halo_to_rv halo_orbit_module::halo_to_rv proc~compute_crtpb_parameter crtbp_module::compute_crtpb_parameter proc~halo_to_rv->proc~compute_crtpb_parameter proc~compute_libration_points crtbp_module::compute_libration_points proc~halo_to_rv->proc~compute_libration_points proc~cube_root math_module::cube_root proc~compute_libration_points->proc~cube_root

Called by

proc~~halo_to_rv~~CalledByGraph proc~halo_to_rv halo_orbit_module::halo_to_rv proc~halo_orbit_test halo_orbit_module::halo_orbit_test proc~halo_orbit_test->proc~halo_to_rv proc~halo_to_rv_diffcorr halo_orbit_module::halo_to_rv_diffcorr proc~halo_to_rv_diffcorr->proc~halo_to_rv

Source Code

    subroutine halo_to_rv(libpoint,mu1,mu2,dist,A_z,n,t1,rv,period)

    implicit none

    integer,intent(in)  :: libpoint         !! Libration point number: [1,2,3]
    real(wp),intent(in) :: mu1              !! grav param for primary body [km3/s2]
    real(wp),intent(in) :: mu2              !! grav param for secondary body [km3/s2]
    real(wp),intent(in) :: dist             !! distance between bodies [km]
    real(wp),intent(in) :: A_z              !! halo z amplitude [km]
    integer,intent(in)  :: n                !! halo family: 1, 3
    real(wp),intent(in) :: t1               !! tau1 [rad]
    real(wp),dimension(6),intent(out) :: rv !! cr3bp normalized state vector
                                            !! [wrt barycenter]
    real(wp),intent(out),optional :: period !! normalized halo orbit period

    real(wp) :: mu          !! CRTBP parameter
    integer  :: delta_n     !! 2 - n
    real(wp) :: gamma_l     !! dimensionless quantity from reference
    real(wp) :: lambda      !! linearized frequency
    real(wp) :: Ax,Ay,Az,Ax2,Az2
    real(wp) :: x,y,z,vx,vy,vz
    real(wp) :: a1,a2,a21,a22,a23,a24,a31,a32,b21,&
                b22,b31,b32,c2,c3,c4,delta,w,&
                d1,d2,d21,d3,d31,d32,k,l1,l2,s1,s2,term
    real(wp),dimension(3) :: x_libpoint  !! x-coordinates of the libration
                                         !! point (wrt barycenter, normalized)
    logical :: ok

    ! error check:
    if (n/=1 .and. n/=3) then
        error stop 'invalid n input to halo_to_rv'
    end if

    ! compute all the intermediate parameters:
    mu = compute_crtpb_parameter(mu1,mu2)

    ! lib point x-coordinate: wrt to barycenter - normalized
    select case (libpoint)
    case(1)
        call compute_libration_points(mu,r1=x_libpoint(1))
        gamma_l = (1.0_wp - mu) - x_libpoint(1)
    case(2)
        call compute_libration_points(mu,r2=x_libpoint(2))
        gamma_l = x_libpoint(2) - ( 1.0_wp - mu )
    case(3)
        call compute_libration_points(mu,r3=x_libpoint(3))
        gamma_l = - (x_libpoint(3) + mu)
    case default
        error stop 'invalid libration point input to halo_to_rv'
    end select

    Az      = A_z / (dist*gamma_l) ! normalized z-Amplitude
    c2      = c_n(libpoint, 2, mu, gamma_l)
    c3      = c_n(libpoint, 3, mu, gamma_l)
    c4      = c_n(libpoint, 4, mu, gamma_l)
    lambda  = sqrt((-c2+two+sqrt(nine*c2**2-eight*c2))/two)  ! root of quartic eqn
    k       = two*lambda/(lambda**2+one-c2)
    delta   = lambda**2-c2
    d1      = 16.0_wp*lambda**4+four*lambda**2*(c2-two)-two*c2**2+c2+one
    d2      = 81.0_wp*lambda**4+nine*lambda**2*(c2-two)-two*c2**2+c2+one
    d3      = two*lambda*(lambda*(one+k**2)-two*k)
    a21     =  three*c3*(k**2-two)/four/(one+two*c2)
    a23     = -three*lambda*c3*(three*k**3*lambda-six*k*(k-lambda)+four)/four/k/d1
    b21     = -three*c3*lambda*(three*lambda*k-four)/two/d1
    s1      = ((three/two)*c3*(two*a21*(k**2-two)-a23*(k**2+two)-&
              two*k*b21)-(three/eight)*c4*(three*k**4-eight*k**2+eight))/d3
    a22     = three*c3/four/(one+two*c2)
    a24     = -three*c3*lambda*(two+three*lambda*k)/four/k/d1
    b22     = three*lambda*c3/d1
    d21     = -c3/two/lambda**2
    s2      = ((three/two)*c3*(two*a22*(k**2-two)+&
              a24*(k**2+two)+two*k*b22+five*d21) + &
              (three/eight)*c4*(12.0_wp-k**2))/d3
    a1      = -(three/two)*c3*(two*a21+a23+five*d21) - &
              (three/eight)*c4*(12.0_wp-k**2)
    a2      = (three/two)*c3*(a24-two*a22)+(nine/eight)*c4
    l1      = two*s1*lambda**2+a1
    l2      = two*s2*lambda**2+a2
    Az2     = Az**2

    ! check if this Az is feasible
    ok = (l1/=zero)
    if (ok) then
        term = (-delta-l2*Az2)/l1
        ok = (term>=zero)
    end if
    if (.not. ok) then
        rv = zero
        if (present(period)) period = zero
        write(error_unit,'(A)') 'Error: infeasible input.'
        return
    end if

    Ax      = sqrt(term) ! equation 18
    Ax2     = Ax**2
    Ay      = k*Ax
    w       = one+s1*Ax2+s2*Az2  ! frequency correction
    a31     = -nine*lambda*(c3*(k*a23-b21)+k*c4*(one+(one/four)*k**2))/d2 + &
              (nine*lambda**2+one-c2)*(three*c3*(two*a23-k*b21)+ &
              c4*(two+three*k**2))/two/d2
    a32     = -nine*lambda*(four*c3*(k*a24-b22)+k*c4)/four/d2 - &
              three*(nine*lambda**2+one-c2)*(c3*(k*b22+d21-two*a24)-c4)/two/d2
    b31     = (three*lambda*(three*c3*(k*b21-two*a23)-c4*(two+three*k**2)) + &
              (nine*lambda**2+1+two*c2)*(12.0_wp*c3*(k*a23-b21)+&
              three*k*c4*(four+k**2))/eight)/d2
    b32     = (three*lambda*(three*c3*(k*b22+d21-two*a24)-three*c4) + &
              (nine*lambda**2+one+two*c2)*(12.0_wp*c3*(k*a24-b22)+three*c4*k)/eight)/d2
    d31     = three*(four*c3*a24+c4)/64.0_wp/lambda**2
    d32     = three*(four*c3*(a23-d21)+c4*(four+k**2))/64.0_wp/lambda**2
    delta_n = 2 - n  ! equation 21

    if (present(period)) period = twopi/(lambda*w)

    ! Equations 20a, 20b, 20c (and their derivatives):
    x  = a21*Ax2+a22*Az2-Ax*cos(t1)+&
         (a23*Ax2-a24*Az2)*cos(two*t1)+&
         (a31*Ax**3-a32*Ax*Az2)*cos(three*t1)
    y  = k*Ax*sin(t1)+(b21*Ax2-b22*Az2)*sin(two*t1)+&
         (b31*Ax**3-b32*Ax*Az2)*sin(three*t1)
    z  = delta_n*(Az*cos(t1)+d21*Ax*Az*(cos(two*t1)-three)+&
         (d32*Az*Ax2-d31*Az**3)*cos(three*t1))
    vx = Ax*sin(t1)-(a23*Ax2-a24*Az2)*sin(two*t1)*two-&
         (a31*Ax**3-a32*Ax*Az2)*sin(three*t1)*three
    vy = k*Ax*cos(t1)+(b21*Ax2-b22*Az2)*cos(two*t1)*two+&
         (b31*Ax**3-b32*Ax*Az2)*cos(three*t1)*three
    vz = delta_n*(-Az*sin(t1)+d21*Ax*Az*(-sin(two*t1)*two)-&
         (d32*Az*Ax2-d31*Az**3)*sin(three*t1)*three)

    rv = [x,y,z,vx,vy,vz]

    ! convert from richardson scale, libration point centered to
    ! standard normalized coordinates wrt barycenter:
    rv(1:3) = rv(1:3) * gamma_l
    rv(4:6) = rv(4:6) * gamma_l * (lambda*w)
    rv(1)   = rv(1) + x_libpoint(libpoint)

    contains
!*******************************************************************************

    !***************************************************************************
        pure function c_n(lib,n,mu,gl) result(cn)

        !! Equations 8a, 8b in the reference.

        implicit none

        integer,intent(in)   :: lib  !! libration point (1,2,3)
        integer,intent(in)   :: n    !! the n in cn
        real(wp),intent(in)  :: mu   !! cr3bp normalized grav parameter
        real(wp),intent(in)  :: gl   !! \( \gamma_l \)
        real(wp)             :: cn   !! result

        ! Equation 8a and 8b:
        select case(lib)
        case(1); cn = (mu+(-1)**n*(one-mu)*(gl/(one-gl))**(n+1)  )/gl**3
        case(2); cn = ((-1)**n*(mu+(one-mu)*(gl/(one+gl))**(n+1)))/gl**3
        case(3); cn = (one-mu+mu*(gl/(one+gl))**(n+1)            )/gl**3
        end select

        end function c_n
    !***************************************************************************

    end subroutine halo_to_rv