Compute the state vector for a halo orbit. This uses the approximation, which is retargeted in the real CR3BP system to produce a periodic orbit.
Todo
use a variable-step size integrator
Type | Intent | Optional | 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] |
|
integer, | intent(out) | :: | info |
status code (1=no errors) |
||
real(kind=wp), | intent(out), | optional | :: | period |
period of halo (normalized time units) |
subroutine halo_to_rv_diffcorr(libpoint,mu1,mu2,dist,A_z,n,t1,rv,info,period) use rk_module use minpack_module use math_module, only: wrap_angle 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] integer,intent(out) :: info !! status code (1=no errors) real(wp),intent(out),optional :: period !! period of halo (normalized time units) integer,parameter :: n_state_vars = 6 !! number of state variables in the equations of motion integer,parameter :: n_opt_vars = 2 !! number of variables in the targeting problem real(wp),parameter :: t0 = 0.0_wp !! initial time (normalized) (epoch doesn't matter for cr3bp) real(wp),parameter :: tol = 1.0e-8_wp !! tolerance for event finding real(wp),parameter :: xtol = 1.0e-6_wp !! tolerance for [[hybrd]] integer,parameter :: maxfev = 1000 !! max number of function evaluations for [[hybrd]] integer,parameter :: n_steps_per_rev = 100 !! number of integration steps per orbit rev type(rk8_10_class) :: prop !! integrator real(wp),dimension(n_opt_vars) :: x_vy0 !! variables in the targeting problem (x0 and vy0) real(wp),dimension(n_opt_vars) :: vx_vzf !! constraints in the targeting problem (vxf and vzf) real(wp),dimension(n_state_vars) :: x0 !! halo initial guess from richardson approximation real(wp),dimension(n_state_vars) :: xf !! state after 1/2 rev (to get the period) real(wp) :: tf_actual !! 1/2 period for retargeted orbit (normalized time) real(wp) :: actual_period !! actual halo orbit period for retargeted orbit (normalized time) real(wp) :: approx_period !! period approximation (normalized time) real(wp) :: dt_to_t1 !! time from `t1=0` to input `t1` real(wp) :: gf !! function value after 1/2 rev (y-coordinate) real(wp) :: tau !! `t1` wrapped from \(- \pi \) to \( \pi \) real(wp) :: dt !! time step (normalized) real(wp) :: tmax !! max final time for event finding integration real(wp) :: mu !! CRTBP parameter ! compute the CRTBP mu parameter: mu = compute_crtpb_parameter(mu1,mu2) ! first we get the halo state approximation at tau1=0: call halo_to_rv(libpoint,mu1,mu2,dist,A_z,n,zero,x0,approx_period) ! for now, fixed number of integration steps per period: dt = approx_period / real(n_steps_per_rev,wp) tmax = two * approx_period ! should be enough to find the x-z crossing ! initialize the integrator: call prop%initialize(n_state_vars,func,g=xz_plane_crossing) ! now, solve for a halo: x_vy0 = [x0(1),x0(5)] ! x0 and vy0 call hybrd1(halo_fcn,2,x_vy0,vx_vzf,tol=xtol,info=info) if (info==1) then ! solution converged ! now have the solution at t1=0: x0(1) = x_vy0(1) x0(5) = x_vy0(2) ! this is the t1 we want: tau = wrap_angle(t1) ! if we need the period: if (present(period) .or. tau/=zero) then ! integrate to the first x-axis crossings (one half rev): ! [need to check output...] call prop%integrate_to_event(t0,x0,dt,tmax,tol,tf_actual,xf,gf) actual_period = two * tf_actual ! normalized period end if ! now we want to propagate to the input tau1 if (tau==zero) then ! already have the solution rv = x0 else ! now, integrate from t1=0 to input t1 to get rv: dt_to_t1 = actual_period * (tau / twopi) call prop%integrate(t0,x0,dt,dt_to_t1,rv) end if if (present(period)) period = actual_period else ! there was an error write(error_unit,'(A)') 'Error: the halo targeting problem did not converge.' rv = x0 end if !call prop%destroy() contains !******************************************************************************* !*************************************************************************** subroutine halo_fcn(n,xvec,fvec,iflag) !! Halo function for [[hybrd1]] implicit none integer,intent(in) :: n !! `n=2` in this case real(wp),dimension(n),intent(in) :: xvec !! x_vy0 real(wp),dimension(n),intent(out) :: fvec !! [vxf,vzf] integer,intent(inout) :: iflag !! status flag (set negative !! to terminate solver) real(wp) :: gf real(wp),dimension(6) :: x,x1,xf x = x0 ! initial guess state (z is held fixed) x(1) = xvec(1) ! x0 x(5) = xvec(2) ! vy0 !integrate to the next x-z-plane crossing: call prop%integrate_to_event(t0,x,dt,tmax,tol,tf_actual,xf,gf) !want x and z-velocity at the x-z-plane crossing to be zero: fvec = [xf(4),xf(6)] end subroutine halo_fcn !*************************************************************************** !*************************************************************************** subroutine func(me,t,x,xdot) !! CRTBP derivative function implicit none class(rk_class),intent(inout) :: me real(wp),intent(in) :: t real(wp),dimension(me%n),intent(in) :: x real(wp),dimension(me%n),intent(out) :: xdot call crtbp_derivs(mu,x,xdot) end subroutine func !************************************************************************** !*************************************************************************** subroutine xz_plane_crossing(me,t,x,g) !! x-z-plane crossing event function implicit none class(rk_class),intent(inout) :: me real(wp),intent(in) :: t real(wp),dimension(me%n),intent(in) :: x real(wp),intent(out) :: g g = x(2) ! y = 0 at x-z-plane crossing end subroutine xz_plane_crossing !*************************************************************************** end subroutine halo_to_rv_diffcorr