Skip to content

Commit

Permalink
✨ Period / CompoundPeriod support in propagate
Browse files Browse the repository at this point in the history
  • Loading branch information
ronisbr committed Jul 2, 2024
1 parent 4dc45ad commit fd2501b
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 46 deletions.
71 changes: 60 additions & 11 deletions src/api/Propagators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,11 @@ name(orbp::OrbitPropagator) = typeof(orbp) |> string

"""
propagate(::Val{:propagator}, Δt::Number, args...; kwargs...) -> SVector{3, T}, SVector{3, T}, OrbitPropagator{Tepoch, T}
propagate(::Val{:propagator}, p::Union{Dates.Period, Dates.CompundPeriod}, args...; kwargs...) -> SVector{3, T}, SVector{3, T}, OrbitPropagator{Tepoch, T}
Initialize the orbit `propagator` and propagate the orbit by `t` [s] from the initial orbit
epoch. The initialization arguments `args...` and `kwargs...` are the same as in the
initialization function [`Propagators.init`](@ref).
Initialize the orbit `propagator` and propagate the orbit by `Δt` [s] or by the period
defined by `p` from the initial orbit epoch. The initialization arguments `args...` and
`kwargs...` are the same as in the initialization function [`Propagators.init`](@ref).
!!! note
Expand All @@ -129,19 +130,25 @@ initialization function [`Propagators.init`](@ref).
instant.
- [`OrbitPropagator{Tepoch, T}`](@ref): Structure with the initialized propagator.
"""
function propagate(prop, Δt::Number, args...; kwargs...)
function propagate(prop::Val, p::Union{Dates.Period, Dates.CompoundPeriod}, args...; kwargs...)
Δt = _toms(p) / 1000
return propagate(prop, Δt, args...; kwargs...)
end

function propagate(prop::Val, Δt::Number, args...; kwargs...)
orbp = Propagators.init(prop, args...; kwargs...)
r_i, v_i = Propagators.propagate!(orbp, Δt)
return r_i, v_i, orbp
end

"""
propagate(::Val{:propagator}, vt::AbstractVector, args...; kwargs...) -> Vector{SVector{3, T}}, Vector{SVector{3, T}}, OrbitPropagator{Tepoch, T}
propagate(::Val{:propagator}, vp::AbstractVector{Union{Dates.Period, Dates.CompundPeriod}}, args...; kwargs...) -> Vector{SVector{3, T}}, Vector{SVector{3, T}}, OrbitPropagator{Tepoch, T}
Initialize the orbit `propagator` and propagate the orbit for every instant defined in `vt`
[s] from the initial orbit epoch. The initialization arguments `args...` and `kwargs...`
(except for `ntasks`) are the same as in the initialization function
[`Propagators.init`](@ref).
[s] or for every period defined in `vp` from the initial orbit epoch. The initialization
arguments `args...` and `kwargs...` (except for `ntasks`) are the same as in the
initialization function [`Propagators.init`](@ref).
!!! note
Expand All @@ -161,16 +168,28 @@ Initialize the orbit `propagator` and propagate the orbit for every instant defi
each propagation instant defined in `vt`.
- [`OrbitPropagator{Tepoch, T}`](@ref): Structure with the initialized propagator.
"""
function propagate(prop, vt::AbstractVector, args...; kwargs...)
function propagate(
prop::Val,
vp::AbstractVector{T},
args...;
kwargs...
) where T<:Dates.CompoundPeriod
vt = _toms.(vp) ./ 1000
return propagate(prop, vt, args...; kwargs...)
end

function propagate(prop::Val, vt::AbstractVector, args...; kwargs...)
orbp = Propagators.init(prop, args...; kwargs...)
vr_i, vv_i = Propagators.propagate!(orbp, vt)
return vr_i, vv_i, orbp
end

"""
propagate!(orbp::OrbitPropagator{Tepoch, T}, t::Number) where {Tepoch, T} -> SVector{3, T}, SVector{3, T}
propagate!(orbp::OrbitPropagator{Tepoch, T}, Δt::Number) where {Tepoch, T} -> SVector{3, T}, SVector{3, T}
propagate!(orbp::OrbitPropagator{Tepoch, T}, p::Union{Dates.Period, Dates.CompoundPeriod}) where {Tepoch, T} -> SVector{3, T}, SVector{3, T}
Propagate the orbit using `orbp` by `t` [s] from the initial orbit epoch.
Propagate the orbit using `orbp` by `Δt` [s] or by the period defined by `p` from the
initial orbit epoch.
# Returns
Expand All @@ -181,10 +200,17 @@ Propagate the orbit using `orbp` by `t` [s] from the initial orbit epoch.
"""
function propagate! end

function propagate!(orbp::OrbitPropagator, p::Union{Dates.Period, Dates.CompoundPeriod})
Δt = _toms(p) / 1000
return propagate!(orbp, Δt)
end

"""
propagate!(orbp::OrbitPropagator{Tepoch, T}, vt::AbstractVector; kwargs...) where {Tepoch <: Number, T <: Number} -> Vector{SVector{3, T}}, Vector{SVector{3, T}}
propagate!(orbp::OrbitPropagator{Tepoch, T}, vp::AbstractVector{Union{Dates.Period, Dates.CompundPeriod}}; kwargs...) where {Tepoch <: Number, T <: Number} -> Vector{SVector{3, T}}, Vector{SVector{3, T}}
Propagate the orbit using `orbp` for every instant defined in `vt` [s].
Propagate the orbit using `orbp` for every instant defined in `vt` [s] or for every period
defined in `vp` from the initial orbit epoch.
# Keywords
Expand All @@ -199,6 +225,15 @@ Propagate the orbit using `orbp` for every instant defined in `vt` [s].
- `Vector{SVector{3, T}}`: Array with the velocity vectors [m / s] in the inertial frame at
each propagation instant defined in `vt`.
"""
function propagate!(
orbp::OrbitPropagator,
vp::AbstractVector{T};
kwargs...
) where T<:Union{Dates.Period, Dates.CompoundPeriod}
vt = _toms.(vp) ./ 1000
return propagate!(orbp, vt; kwargs...)
end

function propagate!(
orbp::OrbitPropagator{Tepoch, T},
vt::AbstractVector;
Expand Down Expand Up @@ -396,4 +431,18 @@ function show(io::IO, mime::MIME"text/plain", orbp::T) where T<:OrbitPropagator
return nothing
end

############################################################################################
# Private Functions #
############################################################################################

# These functions replace `Dates.toms` because the latter is type unstable. For more
# information, see:
#
# https://github.com/JuliaLang/julia/pull/54995

_toms(p::Dates.Period) = Dates.toms(p)
function _toms(p::Dates.CompoundPeriod)
return isempty(p.periods) ? 0.0 : Float64(sum(Dates.toms, p.periods))::Float64
end

end # module Propagator
140 changes: 105 additions & 35 deletions test/api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,53 +67,88 @@ struct DummyPropagator{Tepoch, T} <: OrbitPropagator{Tepoch, T} end
end
end

@testset "DateTime Support" verbose = true begin
@testset "Dates Support" verbose = true begin
jd₀ = date_to_jd(2023, 1, 1, 0, 0, 0)

for (T, j2c) in ((Float64, j2c_egm2008), (Float32, j2c_egm2008_f32))
orb = KeplerianElements(
jd₀,
T(8000e3),
T(0.015),
T(28.5) |> deg2rad,
T(100) |> deg2rad,
T(200) |> deg2rad,
T(45) |> deg2rad
)
@testset "$T" begin
orb = KeplerianElements(
jd₀,
T(8000e3),
T(0.015),
T(28.5) |> deg2rad,
T(100) |> deg2rad,
T(200) |> deg2rad,
T(45) |> deg2rad
)

orbp_ref = Propagators.init(Val(:J2), orb; j2c = j2c)
orbp_ref = Propagators.init(Val(:J2), orb; j2c = j2c)

# == propagate_to_epoch ============================================================
# == propagate =================================================================

r, v, orbp = Propagators.propagate_to_epoch(
Val(:J2),
DateTime("2024-01-01"),
orb;
j2c = j2c
)
r, v, orbp = Propagators.propagate(
Val(:J2),
Dates.Minute(1) + Dates.Second(1),
orb;
j2c = j2c
)

r_ref, v_ref = Propagators.propagate!(orbp_ref, 61)

@test orbp isa typeof(orbp_ref)
@test r isa SVector{3, T}
@test v isa SVector{3, T}
@test r r_ref
@test v v_ref
@test Propagators.last_instant(orbp) == Propagators.last_instant(orbp_ref)

# == propagate! ================================================================

r_ref, v_ref = Propagators.propagate_to_epoch!(orbp_ref, date_to_jd(2024, 1, 1))
orbp = Propagators.init(Val(:J2), orb; j2c = j2c)

r, v = Propagators.propagate!(orbp, Dates.Minute(1) + Dates.Second(1))

r_ref, v_ref = Propagators.propagate!(orbp_ref, 61)

@test orbp isa typeof(orbp_ref)
@test r isa SVector{3, T}
@test v isa SVector{3, T}
@test r r_ref
@test v v_ref
@test Propagators.last_instant(orbp) == Propagators.last_instant(orbp_ref)

@test orbp isa typeof(orbp_ref)
@test r isa SVector{3, T}
@test v isa SVector{3, T}
@test r r_ref
@test v v_ref
@test Propagators.last_instant(orbp) == Propagators.last_instant(orbp_ref)
# == propagate_to_epoch ========================================================

# == propagate_to_epoch! ===========================================================
r, v, orbp = Propagators.propagate_to_epoch(
Val(:J2),
DateTime("2024-01-01"),
orb;
j2c = j2c
)

r_ref, v_ref = Propagators.propagate_to_epoch!(orbp_ref, date_to_jd(2024, 1, 1))

orbp = Propagators.init(Val(:J2), orb; j2c = j2c)
@test orbp isa typeof(orbp_ref)
@test r isa SVector{3, T}
@test v isa SVector{3, T}
@test r r_ref
@test v v_ref
@test Propagators.last_instant(orbp) == Propagators.last_instant(orbp_ref)

r, v = Propagators.propagate_to_epoch!(orbp, DateTime("2024-01-01"))
# == propagate_to_epoch! =======================================================

r_ref, v_ref = Propagators.propagate_to_epoch!(orbp_ref, date_to_jd(2024, 1, 1))
orbp = Propagators.init(Val(:J2), orb; j2c = j2c)

@test r isa SVector{3, T}
@test v isa SVector{3, T}
@test r r_ref
@test v v_ref
@test Propagators.last_instant(orbp) == Propagators.last_instant(orbp_ref)
r, v = Propagators.propagate_to_epoch!(orbp, DateTime("2024-01-01"))

r_ref, v_ref = Propagators.propagate_to_epoch!(orbp_ref, date_to_jd(2024, 1, 1))

@test r isa SVector{3, T}
@test v isa SVector{3, T}
@test r r_ref
@test v v_ref
@test Propagators.last_instant(orbp) == Propagators.last_instant(orbp_ref)
end
end
end

Expand Down Expand Up @@ -151,6 +186,23 @@ end
@test ret[k][2] == v[k]
end

# -- Dates Support -------------------------------------------------------------

vp = [Dates.Second(i) for i in 1:1:100]
ret = Propagators.propagate!.(orbp, 1:1:100)
r, v = Propagators.propagate!(orbp, vp)

@test length(r) == 100
@test length(v) == 100
@test r isa Vector{SVector{3, T}}
@test v isa Vector{SVector{3, T}}
@test Propagators.last_instant(orbp) == 100.0

for k in 1:100
@test ret[k][1] == r[k]
@test ret[k][2] == v[k]
end

# == propagate_to_epoch! =======================================================

vjd = collect(jd₀:0.1:jd₁)
Expand All @@ -168,7 +220,7 @@ end
@test ret[k][2] == v[k]
end

# -- DateTime Support ----------------------------------------------------------
# -- Dates Support -------------------------------------------------------------

vdt = [DateTime(2024, 1, i) for i in 1:30]
ret = Propagators.propagate_to_epoch!.(orbp, vdt)
Expand Down Expand Up @@ -202,6 +254,24 @@ end
@test ret[k][2] == v[k]
end

# -- Dates Support -------------------------------------------------------------

vp = [Dates.Second(i) for i in 1:1:100]
ret = Propagators.propagate!.(orbp, 1:1:100)
r, v, orbp = Propagators.propagate(Val(:J2), vp, orb; j2c = j2c)

@test length(r) == 100
@test length(v) == 100
@test r isa Vector{SVector{3, T}}
@test v isa Vector{SVector{3, T}}
@test orbp isa OrbitPropagatorJ2{Float64, T}
@test Propagators.last_instant(orbp) == 100.0

for k in 1:100
@test ret[k][1] == r[k]
@test ret[k][2] == v[k]
end

end
end
end
Expand Down

0 comments on commit fd2501b

Please sign in to comment.